blob: f5bc79d8003bf7c2d48166bfd8113c588eae02f4 [file] [log] [blame]
Willy Tarreau81f38d62015-04-13 17:11:11 +02001/*
2 * Functions managing applets
3 *
4 * Copyright 2000-2015 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15
16#include <common/config.h>
17#include <common/mini-clist.h>
18#include <proto/applet.h>
Christopher Fauleta73e59b2016-12-09 17:30:18 +010019#include <proto/channel.h>
Willy Tarreau3c595ac2015-04-19 09:59:31 +020020#include <proto/stream.h>
21#include <proto/stream_interface.h>
Willy Tarreau81f38d62015-04-13 17:11:11 +020022
Christopher Faulet1cbe74c2016-12-06 09:13:22 +010023unsigned int nb_applets = 0;
24unsigned int applets_active_queue = 0;
25
Willy Tarreau64bca9d2015-09-25 17:39:23 +020026struct list applet_active_queue = LIST_HEAD_INIT(applet_active_queue);
Christopher Faulet1cbe74c2016-12-06 09:13:22 +010027struct list applet_cur_queue = LIST_HEAD_INIT(applet_cur_queue);
Willy Tarreau3c595ac2015-04-19 09:59:31 +020028
29void applet_run_active()
30{
Willy Tarreau99942382015-09-25 17:56:16 +020031 struct appctx *curr;
Willy Tarreau3c595ac2015-04-19 09:59:31 +020032 struct stream_interface *si;
33
Willy Tarreau99942382015-09-25 17:56:16 +020034 if (LIST_ISEMPTY(&applet_active_queue))
35 return;
36
37 /* move active queue to run queue */
Christopher Faulet1cbe74c2016-12-06 09:13:22 +010038 applet_active_queue.n->p = &applet_cur_queue;
39 applet_active_queue.p->n = &applet_cur_queue;
Willy Tarreau99942382015-09-25 17:56:16 +020040
Christopher Faulet1cbe74c2016-12-06 09:13:22 +010041 applet_cur_queue = applet_active_queue;
Willy Tarreau99942382015-09-25 17:56:16 +020042 LIST_INIT(&applet_active_queue);
43
44 /* The list is only scanned from the head. This guarantees that if any
45 * applet removes another one, there is no side effect while walking
46 * through the list.
47 */
Christopher Faulet1cbe74c2016-12-06 09:13:22 +010048 while (!LIST_ISEMPTY(&applet_cur_queue)) {
49 curr = LIST_ELEM(applet_cur_queue.n, typeof(curr), runq);
Willy Tarreau3c595ac2015-04-19 09:59:31 +020050 si = curr->owner;
51
Christopher Fauleta73e59b2016-12-09 17:30:18 +010052 /* Now we'll try to allocate the input buffer. We wake up the
53 * applet in all cases. So this is the applet responsibility to
54 * check if this buffer was allocated or not. This let a chance
55 * for applets to do some other processing if needed. */
56 if (!channel_alloc_buffer(si_ic(si), &curr->buffer_wait))
57 si_applet_cant_put(si);
Willy Tarreau3c595ac2015-04-19 09:59:31 +020058
Willy Tarreaufe127932015-04-21 19:23:39 +020059 /* We always pretend the applet can't get and doesn't want to
60 * put, it's up to it to change this if needed. This ensures
61 * that one applet which ignores any event will not spin.
62 */
63 si_applet_cant_get(si);
64 si_applet_stop_put(si);
65
Willy Tarreau3c595ac2015-04-19 09:59:31 +020066 curr->applet->fct(curr);
Willy Tarreauaa977ba2015-09-25 11:45:06 +020067 si_applet_wake_cb(si);
Christopher Fauleta73e59b2016-12-09 17:30:18 +010068 channel_release_buffer(si_ic(si), &curr->buffer_wait);
Willy Tarreau99942382015-09-25 17:56:16 +020069
Christopher Faulet1cbe74c2016-12-06 09:13:22 +010070 if (applet_cur_queue.n == &curr->runq) {
Willy Tarreau99942382015-09-25 17:56:16 +020071 /* curr was left in the list, move it back to the active list */
72 LIST_DEL(&curr->runq);
73 LIST_ADDQ(&applet_active_queue, &curr->runq);
74 }
Willy Tarreau3c595ac2015-04-19 09:59:31 +020075 }
76}