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 * 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/* If we haven't seen a heartbeat in the last N seconds, don't count this IP
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * as allive.
b0fb330a8581c8bfab5e523084f9f39264a52b12gsteinmodule AP_MODULE_DECLARE_DATA lbmethod_heartbeat_module;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * configuration structure
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * path: path of the file where the heartbeat information is stored.
b0fb330a8581c8bfab5e523084f9f39264a52b12gsteintypedef struct lb_hb_ctx_t
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein const char *path;
b0fb330a8581c8bfab5e523084f9f39264a52b12gsteintypedef struct hb_server_t {
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein const char *ip;
b0fb330a8581c8bfab5e523084f9f39264a52b12gsteintypedef struct ctx_servers {
1b21d7b3d97def358b2e923655edeb16613a1c31gsteinargstr_to_table(apr_pool_t *p, char *str, apr_table_t *parms)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Found query arg: %s = %s", key, value);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t readfile_heartbeats(const char *path, apr_hash_t *servers,
5b03ba47ff7225cacb131f14b019332af27da960gstein rv = apr_file_open(&fp, path, APR_READ|APR_BINARY|APR_BUFFERED,
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);
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *ip;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (bsize == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* comment */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* line format: <IP> <query_string>\n */
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski server = apr_hash_get(servers, ip, APR_HASH_KEY_STRING);
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe apr_hash_set(servers, server->ip, APR_HASH_KEY_STRING, server);
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.
91644a5f4d3e992dc208304b50e80bbb236fca89trawick } while (1);
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougmstatic apr_status_t hm_read(void* mem, void *data, apr_pool_t *pool)
f4c310fd2555c6faca1f980f00b161eadb089023gstein hm_slot_server_t *slotserver = (hm_slot_server_t *) mem;
f4c310fd2555c6faca1f980f00b161eadb089023gstein hb_server_t *server = apr_hash_get(servers, slotserver->ip, APR_HASH_KEY_STRING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_hash_set(servers, server->ip, APR_HASH_KEY_STRING, server);
f4c310fd2555c6faca1f980f00b161eadb089023gstein server->seen = apr_time_sec(ctx->now - slotserver->seen);
48f35e10f195dd594d75738fc536bb885eda537cgsteinstatic apr_status_t readslot_heartbeats(ctx_servers_t *ctx,
48f35e10f195dd594d75738fc536bb885eda537cgsteinstatic apr_status_t read_heartbeats(const char *path, apr_hash_t *servers,
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gsteinstatic proxy_worker *find_best_hb(proxy_balancer *balancer,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "lb_heartbeat: Unable to read heartbeats at '%s'",
f4c310fd2555c6faca1f980f00b161eadb089023gstein up_servers = apr_array_make(tpool, apr_hash_count(servers), sizeof(hb_server_t *));
48f35e10f195dd594d75738fc536bb885eda537cgstein worker = &APR_ARRAY_IDX(balancer->workers, i, proxy_worker *);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm server = apr_hash_get(servers, (*worker)->s->hostname, APR_HASH_KEY_STRING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein "lb_heartbeat: No server for worker %s", (*worker)->s->name);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_proxy_retry_worker("BALANCER", *worker, r->server);
f4c310fd2555c6faca1f980f00b161eadb089023gstein server = APR_ARRAY_IDX(up_servers, i, hb_server_t *);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t reset(proxy_balancer *balancer, server_rec *s) {
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t age(proxy_balancer *balancer, server_rec *s) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein "heartbeat",
f39230a531b23d94f86a087963299bbe2e431a4agsteinstatic int lb_hb_init(apr_pool_t *p, apr_pool_t *plog,
f39230a531b23d94f86a087963299bbe2e431a4agstein unsigned int num;
f39230a531b23d94f86a087963299bbe2e431a4agstein lb_hb_ctx_t *ctx = ap_get_module_config(s->module_config,
f39230a531b23d94f86a087963299bbe2e431a4agstein /* do nothing on first call */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein storage = ap_lookup_provider(AP_SLOTMEM_PROVIDER_GROUP, "shared",
f39230a531b23d94f86a087963299bbe2e431a4agstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, s, "ap_lookup_provider %s failed", AP_SLOTMEM_PROVIDER_GROUP);
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein /* Try to use a slotmem created by mod_heartmonitor */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein storage->attach(&hm_serversmem, "mod_heartmonitor", &size, &num, p);
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, s, "No slotmem from mod_heartmonitor");
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, s, "Using slotmem from mod_heartmonitor");
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);
f39230a531b23d94f86a087963299bbe2e431a4agsteinstatic void *lb_hb_create_config(apr_pool_t *p, server_rec *s)
f39230a531b23d94f86a087963299bbe2e431a4agstein lb_hb_ctx_t *ctx = (lb_hb_ctx_t *) apr_palloc(p, sizeof(lb_hb_ctx_t));
f39230a531b23d94f86a087963299bbe2e431a4agstein ctx->path = ap_server_root_relative(p, "logs/hb.dat");
f39230a531b23d94f86a087963299bbe2e431a4agsteinstatic void *lb_hb_merge_config(apr_pool_t *p, void *basev, void *overridesv)
f39230a531b23d94f86a087963299bbe2e431a4agstein lb_hb_ctx_t *ps = apr_pcalloc(p, sizeof(lb_hb_ctx_t));
f39230a531b23d94f86a087963299bbe2e431a4agstein (lb_hb_ctx_t *) ap_get_module_config(cmd->server->module_config,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein AP_INIT_TAKE1("HeartbeatStorage", cmd_lb_hb_storage, NULL, RSRC_CONF,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein "Path to read heartbeat data."),
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein lb_hb_create_config, /* create per-server config structure */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein lb_hb_merge_config, /* merge per-server config structures */