You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Paul Querna <pa...@querna.org> on 2009/03/29 14:42:59 UTC

Re: svn commit: r759386 - in /httpd/httpd/trunk/modules/proxy: mod_serf.c mod_serf.h

On Sun, Mar 29, 2009 at 11:05 AM, Ruediger Pluem <rp...@apache.org> wrote:
> On 03/28/2009 12:10 AM, pquerna@apache.org wrote:
>> Author: pquerna
>> Date: Fri Mar 27 23:10:21 2009
>> New Revision: 759386
>>
>> URL: http://svn.apache.org/viewvc?rev=759386&view=rev
....
>> +static void * merge_server_config(apr_pool_t *p, void *basev, void *overridesv)
>> +{
>> +    serf_server_config_t *ctx = apr_pcalloc(p, sizeof(serf_server_config_t));
>> +    serf_server_config_t *base = (serf_server_config_t *) basev;
>> +    serf_server_config_t *overrides = (serf_server_config_t *) overridesv;
>> +
>> +    ctx->clusters = apr_hash_overlay(p, base->clusters, overrides->clusters);
>> +    return ctx;
>> +}
>
>
> Why do we need merging when the directive is global only?

I intend to change it to not be global only....  There is no reason
SerfCluster can't be server/vhost scoped.

>> +
>>  static const command_rec serf_cmds[] =
>>  {
>> -    AP_INIT_TAKE1("SerfPass", add_pass, NULL, OR_INDEXES/*making shit up*/,
>> -     "A prefix and destination"),
>> +    AP_INIT_TAKE_ARGV("SerfCluster", add_cluster, NULL, RSRC_CONF,
>> +                      "Configure a cluster backend"),
>> +    AP_INIT_TAKE1("SerfPass", add_pass, NULL, OR_INDEXES,
>> +                  "URL to reverse proxy to"),
>>      {NULL}
>>  };
>>
>> +typedef struct hb_table_baton_t {
>> +    apr_pool_t *p;
>> +    const char *msg;
>> +} hb_table_baton_t;
>> +
>> +static int hb_table_check(void *rec, const char *key, const char *value)
>> +{
>> +    hb_table_baton_t *b = (hb_table_baton_t*)rec;
>> +    if (strcmp(key, "path") != 0) {
>> +        b->msg = apr_psprintf(b->p,
>> +                              "SerfCluster Heartbeat Invalid parameter '%s'",
>> +                              key);
>> +        return 1;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static const char* hb_config_check(void *baton,
>> +                                   cmd_parms *cmd,
>> +                                   apr_table_t *params)
>> +{
>> +    hb_table_baton_t b;
>> +
>> +    if (apr_is_empty_table(params)) {
>> +        return "SerfCluster Heartbeat requires a path to the heartbat information.";
>> +    }
>> +
>> +    b.p = cmd->pool;
>> +    b.msg = NULL;
>> +
>> +    apr_table_do(hb_table_check, &b, params, NULL);
>> +
>> +    if (b.msg) {
>> +        return b.msg;
>> +    }
>> +
>> +    return NULL;
>> +}
>> +
>> +typedef struct hb_server_t {
>> +    const char *ip;
>> +    int busy;
>> +    int ready;
>> +    int seen;
>> +} hb_server_t;
>> +
>> +static void
>> +argstr_to_table(apr_pool_t *p, char *str, apr_table_t *parms)
>> +{
>> +    char *key;
>> +    char *value;
>> +    char *strtok_state;
>> +
>> +    key = apr_strtok(str, "&", &strtok_state);
>> +    while (key) {
>> +        value = strchr(key, '=');
>> +        if (value) {
>> +            *value = '\0';      /* Split the string in two */
>> +            value++;            /* Skip passed the = */
>> +        }
>> +        else {
>> +            value = "1";
>> +        }
>> +        ap_unescape_url(key);
>> +        ap_unescape_url(value);
>> +        apr_table_set(parms, key, value);
>> +        key = apr_strtok(NULL, "&", &strtok_state);
>> +    }
>> +}
>> +
>> +static apr_status_t read_heartbeats(const char *path,
>> +                                    apr_array_header_t *servers,
>> +                                    apr_pool_t *pool)
>> +{
>> +    apr_finfo_t fi;
>> +    apr_status_t rv;
>> +    apr_file_t *fp;
>> +
>> +    if (!path) {
>> +        return APR_SUCCESS;
>> +    }
>> +
>> +    rv = apr_file_open(&fp, path, APR_READ|APR_BINARY|APR_BUFFERED,
>> +                       APR_OS_DEFAULT, pool);
>> +
>> +    if (rv) {
>> +        return rv;
>> +    }
>> +
>> +    rv = apr_file_info_get(&fi, APR_FINFO_SIZE, fp);
>> +
>> +    if (rv) {
>> +        return rv;
>> +    }
>> +
>> +    {
>> +        char *t;
>> +        int lineno = 0;
>> +        apr_table_t *hbt = apr_table_make(pool, 10);
>> +        char buf[4096];
>> +
>> +        while (apr_file_gets(buf, sizeof(buf), fp) == APR_SUCCESS) {
>> +            hb_server_t *server;
>> +            const char *ip;
>> +            lineno++;
>> +
>> +            /* comment */
>> +            if (buf[0] == '#') {
>> +                continue;
>> +            }
>> +
>> +
>> +            /* line format: <IP> <query_string>\n */
>> +            t = strchr(buf, ' ');
>> +            if (!t) {
>> +                continue;
>> +            }
>> +
>> +            ip = apr_pstrndup(pool, buf, t - buf);
>> +            t++;
>> +            server = apr_pcalloc(pool, sizeof(hb_server_t));
>> +            server->ip = ip;
>> +            server->seen = -1;
>> +            apr_table_clear(hbt);
>> +
>> +            argstr_to_table(pool, apr_pstrdup(pool, t), hbt);
>> +
>> +            if (apr_table_get(hbt, "busy")) {
>> +                server->busy = atoi(apr_table_get(hbt, "busy"));
>> +            }
>> +
>> +            if (apr_table_get(hbt, "ready")) {
>> +                server->ready = atoi(apr_table_get(hbt, "ready"));
>> +            }
>> +
>> +            if (apr_table_get(hbt, "lastseen")) {
>> +                server->seen = atoi(apr_table_get(hbt, "lastseen"));
>> +            }
>> +
>> +            if (server->busy == 0 && server->ready != 0) {
>> +                /* Server has zero threads active, but lots of them ready,
>> +                 * it likely just started up, so lets /4 the number ready,
>> +                 * to prevent us from completely flooding it with all new
>> +                 * requests.
>> +                 */
>> +                server->ready = server->ready / 4;
>
> Nitpick: server->ready = server->ready >> 2 seems to be better.
>
>> +            }
>> +
>> +            APR_ARRAY_PUSH(servers, hb_server_t *) = server;
>> +        }
>> +    }
>> +
>> +    return APR_SUCCESS;
>> +}
>> +
>> +static int hb_server_sort(const void *a_, const void *b_)
>> +{
>> +    hb_server_t *a = (hb_server_t*)a;
>> +    hb_server_t *b = (hb_server_t*)b;
>
> Guess that should be a_ and b_ above.
>

oh duh. fixed in r759673.

>> +    if (a->ready == b->ready) {
>> +        return 0;
>> +    }
>> +    else if (a->ready > b->ready) {
>> +        return -1;
>> +    }
>> +    else {
>> +        return 1;
>> +    }
>> +}
>
>
> Regards
>
> Rüdiger

Thanks for reviewing,

Paul