mod_lbmethod_heartbeat.c revision 7bf4eb9638a127fbfbc402d2c0e4ec0085934cf0
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein/* Licensed to the Apache Software Foundation (ASF) under one or more
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * contributor license agreements. See the NOTICE file distributed with
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * this work for additional information regarding copyright ownership.
bc8fd1b0b1afdf89b8d28eefa8cd74e26ba97986fielding * The ASF licenses this file to You under the Apache License, Version 2.0
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * (the "License"); you may not use this file except in compliance with
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * the License. You may obtain a copy of the License at
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * http://www.apache.org/licenses/LICENSE-2.0
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Unless required by applicable law or agreed to in writing, software
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * distributed under the License is distributed on an "AS IS" BASIS,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * See the License for the specific language governing permissions and
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * limitations under the License.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein */
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "mod_proxy.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "scoreboard.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "ap_mpm.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_version.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "ap_hooks.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "ap_slotmem.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "heartbeat.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#ifndef LBM_HEARTBEAT_MAX_LASTSEEN
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein/* If we haven't seen a heartbeat in the last N seconds, don't count this IP
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * as allive.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein */
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#define LBM_HEARTBEAT_MAX_LASTSEEN (10)
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#endif
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gsteinmodule AP_MODULE_DECLARE_DATA lbmethod_heartbeat_module;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gsteinstatic const ap_slotmem_provider_t *storage = NULL;
b0fb330a8581c8bfab5e523084f9f39264a52b12gsteinstatic ap_slotmem_instance_t *hm_serversmem = NULL;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein/*
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * configuration structure
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * path: path of the file where the heartbeat information is stored.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein */
b0fb330a8581c8bfab5e523084f9f39264a52b12gsteintypedef struct lb_hb_ctx_t
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein{
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein const char *path;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein} lb_hb_ctx_t;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gsteintypedef struct hb_server_t {
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein const char *ip;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein int busy;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein int ready;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein int port;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein int id;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein apr_time_t seen;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein proxy_worker *worker;
f4c310fd2555c6faca1f980f00b161eadb089023gstein} hb_server_t;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gsteintypedef struct ctx_servers {
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_time_t now;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_hash_t *servers;
f4c310fd2555c6faca1f980f00b161eadb089023gstein} ctx_servers_t;
1b21d7b3d97def358b2e923655edeb16613a1c31gstein
952023a04a2f9d51553babd9094fb857f1c97548trawickstatic void
1b21d7b3d97def358b2e923655edeb16613a1c31gsteinargstr_to_table(apr_pool_t *p, char *str, apr_table_t *parms)
1b21d7b3d97def358b2e923655edeb16613a1c31gstein{
1b21d7b3d97def358b2e923655edeb16613a1c31gstein char *key;
1b21d7b3d97def358b2e923655edeb16613a1c31gstein char *value;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *strtok_state;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein key = apr_strtok(str, "&", &strtok_state);
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (key) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein value = strchr(key, '=');
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (value) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *value = '\0'; /* Split the string in two */
f4c310fd2555c6faca1f980f00b161eadb089023gstein value++; /* Skip passed the = */
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe }
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein value = "1";
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ap_unescape_url(key);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_unescape_url(value);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_table_set(parms, key, value);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Found query arg: %s = %s", key, value);
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein key = apr_strtok(NULL, "&", &strtok_state);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t readfile_heartbeats(const char *path, apr_hash_t *servers,
5b03ba47ff7225cacb131f14b019332af27da960gstein apr_pool_t *pool)
5b03ba47ff7225cacb131f14b019332af27da960gstein{
5b03ba47ff7225cacb131f14b019332af27da960gstein apr_finfo_t fi;
5b03ba47ff7225cacb131f14b019332af27da960gstein apr_status_t rv;
5b03ba47ff7225cacb131f14b019332af27da960gstein apr_file_t *fp;
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein if (!path) {
5b03ba47ff7225cacb131f14b019332af27da960gstein return APR_SUCCESS;
5b03ba47ff7225cacb131f14b019332af27da960gstein }
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein rv = apr_file_open(&fp, path, APR_READ|APR_BINARY|APR_BUFFERED,
5b03ba47ff7225cacb131f14b019332af27da960gstein APR_OS_DEFAULT, pool);
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein if (rv) {
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe return rv;
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe }
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = apr_file_info_get(&fi, APR_FINFO_SIZE, fp);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein {
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *t;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int lineno = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_bucket_alloc_t *ba = apr_bucket_alloc_create(pool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_bucket_brigade *bb = apr_brigade_create(pool, ba);
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe apr_bucket_brigade *tmpbb = apr_brigade_create(pool, ba);
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe apr_table_t *hbt = apr_table_make(pool, 10);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_brigade_insert_file(bb, fp, 0, fi.size, pool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein do {
f4c310fd2555c6faca1f980f00b161eadb089023gstein hb_server_t *server;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char buf[4096];
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_size_t bsize = sizeof(buf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *ip;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_brigade_cleanup(tmpbb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (APR_BRIGADE_EMPTY(bb)) {
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe break;
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = apr_brigade_split_line(tmpbb, bb,
f4c310fd2555c6faca1f980f00b161eadb089023gstein APR_BLOCK_READ, sizeof(buf));
f4c310fd2555c6faca1f980f00b161eadb089023gstein lineno++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_brigade_flatten(tmpbb, buf, &bsize);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (bsize == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein buf[bsize - 1] = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* comment */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (buf[0] == '#') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe }
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* line format: <IP> <query_string>\n */
f4c310fd2555c6faca1f980f00b161eadb089023gstein t = strchr(buf, ' ');
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!t) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe ip = apr_pstrndup(pool, buf, t - buf);
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe t++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski server = apr_hash_get(servers, ip, APR_HASH_KEY_STRING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (server == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein server = apr_pcalloc(pool, sizeof(hb_server_t));
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->ip = ip;
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->port = 80;
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->seen = -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe apr_hash_set(servers, server->ip, APR_HASH_KEY_STRING, server);
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski apr_table_clear(hbt);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein argstr_to_table(pool, apr_pstrdup(pool, t), hbt);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (apr_table_get(hbt, "busy")) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->busy = atoi(apr_table_get(hbt, "busy"));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe if (apr_table_get(hbt, "ready")) {
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe server->ready = atoi(apr_table_get(hbt, "ready"));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (apr_table_get(hbt, "lastseen")) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->seen = atoi(apr_table_get(hbt, "lastseen"));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (apr_table_get(hbt, "port")) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->port = atoi(apr_table_get(hbt, "port"));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (server->busy == 0 && server->ready != 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Server has zero threads active, but lots of them ready,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * it likely just started up, so lets /4 the number ready,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * to prevent us from completely flooding it with all new
48f35e10f195dd594d75738fc536bb885eda537cgstein * requests.
48f35e10f195dd594d75738fc536bb885eda537cgstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->ready = server->ready / 4;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
91644a5f4d3e992dc208304b50e80bbb236fca89trawick } while (1);
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougmstatic apr_status_t hm_read(void* mem, void *data, apr_pool_t *pool)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein hm_slot_server_t *slotserver = (hm_slot_server_t *) mem;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx_servers_t *ctx = (ctx_servers_t *) data;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_hash_t *servers = (apr_hash_t *) ctx->servers;
f4c310fd2555c6faca1f980f00b161eadb089023gstein hb_server_t *server = apr_hash_get(servers, slotserver->ip, APR_HASH_KEY_STRING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (server == NULL) {
48f35e10f195dd594d75738fc536bb885eda537cgstein server = apr_pcalloc(pool, sizeof(hb_server_t));
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->ip = apr_pstrdup(pool, slotserver->ip);
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->seen = -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_hash_set(servers, server->ip, APR_HASH_KEY_STRING, server);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
48f35e10f195dd594d75738fc536bb885eda537cgstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->busy = slotserver->busy;
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->ready = slotserver->ready;
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->seen = apr_time_sec(ctx->now - slotserver->seen);
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->id = slotserver->id;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (server->busy == 0 && server->ready != 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->ready = server->ready / 4;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
48f35e10f195dd594d75738fc536bb885eda537cgstein}
48f35e10f195dd594d75738fc536bb885eda537cgsteinstatic apr_status_t readslot_heartbeats(ctx_servers_t *ctx,
48f35e10f195dd594d75738fc536bb885eda537cgstein apr_pool_t *pool)
48f35e10f195dd594d75738fc536bb885eda537cgstein{
48f35e10f195dd594d75738fc536bb885eda537cgstein storage->doall(hm_serversmem, hm_read, ctx, pool);
48f35e10f195dd594d75738fc536bb885eda537cgstein return APR_SUCCESS;
48f35e10f195dd594d75738fc536bb885eda537cgstein}
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgsteinstatic apr_status_t read_heartbeats(const char *path, apr_hash_t *servers,
48f35e10f195dd594d75738fc536bb885eda537cgstein apr_pool_t *pool)
48f35e10f195dd594d75738fc536bb885eda537cgstein{
48f35e10f195dd594d75738fc536bb885eda537cgstein apr_status_t rv;
48f35e10f195dd594d75738fc536bb885eda537cgstein if (hm_serversmem) {
48f35e10f195dd594d75738fc536bb885eda537cgstein ctx_servers_t ctx;
48f35e10f195dd594d75738fc536bb885eda537cgstein ctx.now = apr_time_now();
48f35e10f195dd594d75738fc536bb885eda537cgstein ctx.servers = servers;
24efed0910118b762a4eb84830875d4714b8d315ianh rv = readslot_heartbeats(&ctx, pool);
48f35e10f195dd594d75738fc536bb885eda537cgstein } else
48f35e10f195dd594d75738fc536bb885eda537cgstein rv = readfile_heartbeats(path, servers, pool);
48f35e10f195dd594d75738fc536bb885eda537cgstein return rv;
48f35e10f195dd594d75738fc536bb885eda537cgstein}
48f35e10f195dd594d75738fc536bb885eda537cgstein
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gsteinstatic proxy_worker *find_best_hb(proxy_balancer *balancer,
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein request_rec *r)
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein{
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein apr_status_t rv;
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein int i;
48f35e10f195dd594d75738fc536bb885eda537cgstein apr_uint32_t openslots = 0;
48f35e10f195dd594d75738fc536bb885eda537cgstein proxy_worker **worker;
48f35e10f195dd594d75738fc536bb885eda537cgstein hb_server_t *server;
48f35e10f195dd594d75738fc536bb885eda537cgstein apr_array_header_t *up_servers;
48f35e10f195dd594d75738fc536bb885eda537cgstein proxy_worker *mycandidate = NULL;
48f35e10f195dd594d75738fc536bb885eda537cgstein apr_pool_t *tpool;
48f35e10f195dd594d75738fc536bb885eda537cgstein apr_hash_t *servers;
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgstein lb_hb_ctx_t *ctx =
48f35e10f195dd594d75738fc536bb885eda537cgstein ap_get_module_config(r->server->module_config,
48f35e10f195dd594d75738fc536bb885eda537cgstein &lbmethod_heartbeat_module);
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgstein apr_pool_create(&tpool, r->pool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein servers = apr_hash_make(tpool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = read_heartbeats(ctx->path, servers, tpool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "lb_heartbeat: Unable to read heartbeats at '%s'",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->path);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_destroy(tpool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein up_servers = apr_array_make(tpool, apr_hash_count(servers), sizeof(hb_server_t *));
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgstein for (i = 0; i < balancer->workers->nelts; i++) {
48f35e10f195dd594d75738fc536bb885eda537cgstein worker = &APR_ARRAY_IDX(balancer->workers, i, proxy_worker *);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm server = apr_hash_get(servers, (*worker)->s->hostname, APR_HASH_KEY_STRING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!server) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "lb_heartbeat: No server for worker %s", (*worker)->s->name);
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!PROXY_WORKER_IS_USABLE(*worker)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_proxy_retry_worker("BALANCER", *worker, r->server);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (PROXY_WORKER_IS_USABLE(*worker)) {
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein server->worker = *worker;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (server->seen < LBM_HEARTBEAT_MAX_LASTSEEN) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein openslots += server->ready;
f4c310fd2555c6faca1f980f00b161eadb089023gstein APR_ARRAY_PUSH(up_servers, hb_server_t *) = server;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (openslots > 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_uint32_t c = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_uint32_t pick = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein pick = ap_random_pick(0, openslots);
f958dac1550254a59b45f4655138bb34dad5e76egstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < up_servers->nelts; i++) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein server = APR_ARRAY_IDX(up_servers, i, hb_server_t *);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pick >= c && pick <= c + server->ready) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein mycandidate = server->worker;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein c += server->ready;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_pool_destroy(tpool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return mycandidate;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t reset(proxy_balancer *balancer, server_rec *s) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t age(proxy_balancer *balancer, server_rec *s) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowestatic const proxy_balancer_method heartbeat =
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein "heartbeat",
f4c310fd2555c6faca1f980f00b161eadb089023gstein &find_best_hb,
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL,
f39230a531b23d94f86a087963299bbe2e431a4agstein &reset,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe &age
f39230a531b23d94f86a087963299bbe2e431a4agstein};
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agsteinstatic int lb_hb_init(apr_pool_t *p, apr_pool_t *plog,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_pool_t *ptemp, server_rec *s)
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe{
f39230a531b23d94f86a087963299bbe2e431a4agstein apr_size_t size;
f39230a531b23d94f86a087963299bbe2e431a4agstein unsigned int num;
f39230a531b23d94f86a087963299bbe2e431a4agstein lb_hb_ctx_t *ctx = ap_get_module_config(s->module_config,
1e2133fe37e6cbcd683233057ef62236bc8e5826trawick &lbmethod_heartbeat_module);
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein
f39230a531b23d94f86a087963299bbe2e431a4agstein /* do nothing on first call */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein return OK;
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein storage = ap_lookup_provider(AP_SLOTMEM_PROVIDER_GROUP, "shared",
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein AP_SLOTMEM_PROVIDER_VERSION);
f39230a531b23d94f86a087963299bbe2e431a4agstein if (!storage) {
f39230a531b23d94f86a087963299bbe2e431a4agstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, s, "ap_lookup_provider %s failed", AP_SLOTMEM_PROVIDER_GROUP);
f39230a531b23d94f86a087963299bbe2e431a4agstein return OK;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein /* Try to use a slotmem created by mod_heartmonitor */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein storage->attach(&hm_serversmem, "mod_heartmonitor", &size, &num, p);
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein if (!hm_serversmem) {
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, s, "No slotmem from mod_heartmonitor");
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein } else
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, s, "Using slotmem from mod_heartmonitor");
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein if (hm_serversmem)
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ctx->path = "(slotmem)";
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein return OK;
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein}
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gsteinstatic void register_hooks(apr_pool_t *p)
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein{
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein static const char * const aszPred[]={ "mod_heartmonitor.c", NULL };
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_register_provider(p, PROXY_LBMETHOD, "heartbeat", "0", &heartbeat);
f39230a531b23d94f86a087963299bbe2e431a4agstein ap_hook_post_config(lb_hb_init, aszPred, NULL, APR_HOOK_MIDDLE);
f39230a531b23d94f86a087963299bbe2e431a4agstein}
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agsteinstatic void *lb_hb_create_config(apr_pool_t *p, server_rec *s)
f39230a531b23d94f86a087963299bbe2e431a4agstein{
f39230a531b23d94f86a087963299bbe2e431a4agstein lb_hb_ctx_t *ctx = (lb_hb_ctx_t *) apr_palloc(p, sizeof(lb_hb_ctx_t));
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein ctx->path = ap_server_root_relative(p, "logs/hb.dat");
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein return ctx;
f39230a531b23d94f86a087963299bbe2e431a4agstein}
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agsteinstatic void *lb_hb_merge_config(apr_pool_t *p, void *basev, void *overridesv)
f39230a531b23d94f86a087963299bbe2e431a4agstein{
f39230a531b23d94f86a087963299bbe2e431a4agstein lb_hb_ctx_t *ps = apr_pcalloc(p, sizeof(lb_hb_ctx_t));
f39230a531b23d94f86a087963299bbe2e431a4agstein lb_hb_ctx_t *base = (lb_hb_ctx_t *) basev;
f39230a531b23d94f86a087963299bbe2e431a4agstein lb_hb_ctx_t *overrides = (lb_hb_ctx_t *) overridesv;
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein if (overrides->path) {
f39230a531b23d94f86a087963299bbe2e431a4agstein ps->path = apr_pstrdup(p, overrides->path);
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein else {
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ps->path = apr_pstrdup(p, base->path);
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein return ps;
f39230a531b23d94f86a087963299bbe2e431a4agstein}
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agsteinstatic const char *cmd_lb_hb_storage(cmd_parms *cmd,
f39230a531b23d94f86a087963299bbe2e431a4agstein void *dconf, const char *path)
f39230a531b23d94f86a087963299bbe2e431a4agstein{
f39230a531b23d94f86a087963299bbe2e431a4agstein apr_pool_t *p = cmd->pool;
f39230a531b23d94f86a087963299bbe2e431a4agstein lb_hb_ctx_t *ctx =
f39230a531b23d94f86a087963299bbe2e431a4agstein (lb_hb_ctx_t *) ap_get_module_config(cmd->server->module_config,
f39230a531b23d94f86a087963299bbe2e431a4agstein &lbmethod_heartbeat_module);
f39230a531b23d94f86a087963299bbe2e431a4agstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (err != NULL) {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein return err;
6810bf1570bed88d16239b27ce47d48408bb2e51gstein }
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein ctx->path = ap_server_root_relative(p, path);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein return NULL;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein}
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic const command_rec cmds[] = {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein AP_INIT_TAKE1("HeartbeatStorage", cmd_lb_hb_storage, NULL, RSRC_CONF,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein "Path to read heartbeat data."),
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein {NULL}
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein};
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinAP_DECLARE_MODULE(lbmethod_heartbeat) = {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein STANDARD20_MODULE_STUFF,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein NULL, /* create per-directory config structure */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein NULL, /* merge per-directory config structures */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein lb_hb_create_config, /* create per-server config structure */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein lb_hb_merge_config, /* merge per-server config structures */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein cmds, /* command apr_table_t */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein register_hooks /* register hooks */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein};
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein