"Fossies" - the Fresh Open Source Software Archive

Member "haproxy-2.0.9/src/applet.c" (15 Nov 2019, 3461 Bytes) of package /linux/misc/haproxy-2.0.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "applet.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.0.7_vs_2.0.8.

    1 /*
    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>
   19 #include <proto/channel.h>
   20 #include <proto/stream.h>
   21 #include <proto/stream_interface.h>
   22 #include <proto/task.h>
   23 
   24 unsigned int nb_applets = 0;
   25 
   26 /* Callback used to wake up an applet when a buffer is available. The applet
   27  * <appctx> is woken up if an input buffer was requested for the associated
   28  * stream interface. In this case the buffer is immediately allocated and the
   29  * function returns 1. Otherwise it returns 0. Note that this automatically
   30  * covers multiple wake-up attempts by ensuring that the same buffer will not
   31  * be accounted for multiple times.
   32  */
   33 int appctx_buf_available(void *arg)
   34 {
   35     struct appctx *appctx = arg;
   36     struct stream_interface *si = appctx->owner;
   37 
   38     /* allocation requested ? */
   39     if (!(si->flags & SI_FL_RXBLK_BUFF))
   40         return 0;
   41 
   42     si_rx_buff_rdy(si);
   43 
   44     /* was already allocated another way ? if so, don't take this one */
   45     if (c_size(si_ic(si)) || si_ic(si)->pipe)
   46         return 0;
   47 
   48     /* allocation possible now ? */
   49     if (!b_alloc_margin(&si_ic(si)->buf, global.tune.reserved_bufs)) {
   50         si_rx_buff_blk(si);
   51         return 0;
   52     }
   53 
   54     task_wakeup(appctx->t, TASK_WOKEN_RES);
   55     return 1;
   56 }
   57 
   58 /* Default applet handler */
   59 struct task *task_run_applet(struct task *t, void *context, unsigned short state)
   60 {
   61     struct appctx *app = context;
   62     struct stream_interface *si = app->owner;
   63     unsigned int rate;
   64 
   65     if (app->state & APPLET_WANT_DIE) {
   66         __appctx_free(app);
   67         return NULL;
   68     }
   69 
   70     /* We always pretend the applet can't get and doesn't want to
   71      * put, it's up to it to change this if needed. This ensures
   72      * that one applet which ignores any event will not spin.
   73      */
   74     si_cant_get(si);
   75     si_rx_endp_done(si);
   76 
   77     /* Now we'll try to allocate the input buffer. We wake up the applet in
   78      * all cases. So this is the applet's responsibility to check if this
   79      * buffer was allocated or not. This leaves a chance for applets to do
   80      * some other processing if needed. The applet doesn't have anything to
   81      * do if it needs the buffer, it will be called again upon readiness.
   82      */
   83     if (!si_alloc_ibuf(si, &app->buffer_wait))
   84         si_rx_endp_more(si);
   85 
   86     app->applet->fct(app);
   87 
   88     /* measure the call rate and check for anomalies when too high */
   89     rate = update_freq_ctr(&app->call_rate, 1);
   90     if (rate >= 100000 && app->call_rate.prev_ctr && // looped more than 100k times over last second
   91         ((b_size(si_ib(si)) && si->flags & SI_FL_RXBLK_BUFF) || // asks for a buffer which is present
   92          (b_size(si_ib(si)) && !b_data(si_ib(si)) && si->flags & SI_FL_RXBLK_ROOM) || // asks for room in an empty buffer
   93          (b_data(si_ob(si)) && si_tx_endp_ready(si) && !si_tx_blocked(si)) || // asks for data already present
   94          (!b_data(si_ib(si)) && b_data(si_ob(si)) && // didn't return anything ...
   95           (si_oc(si)->flags & (CF_WRITE_PARTIAL|CF_SHUTW_NOW)) == CF_SHUTW_NOW))) { // ... and left data pending after a shut
   96         stream_dump_and_crash(&app->obj_type, read_freq_ctr(&app->call_rate));
   97     }
   98 
   99     si_applet_wake_cb(si);
  100     channel_release_buffer(si_ic(si), &app->buffer_wait);
  101     return t;
  102 }
  103