mod_heartmonitor.c revision eec239e376d6338d3e89c39ad3c1f8934ff09af3
0922cbe8300e97215564748d449824f458196335Lennart Poettering/* Licensed to the Apache Software Foundation (ASF) under one or more
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * contributor license agreements. See the NOTICE file distributed with
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * this work for additional information regarding copyright ownership.
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * The ASF licenses this file to You under the Apache License, Version 2.0
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * (the "License"); you may not use this file except in compliance with
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * the License. You may obtain a copy of the License at
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * http://www.apache.org/licenses/LICENSE-2.0
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * Unless required by applicable law or agreed to in writing, software
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * distributed under the License is distributed on an "AS IS" BASIS,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * See the License for the specific language governing permissions and
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * limitations under the License.
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering/* How often we update the stats file */
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering/* TODO: Make a runtime config */
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering#define HM_WATHCHDOG_NAME ("_heartmonitor_")
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poetteringmodule AP_MODULE_DECLARE_DATA heartmonitor_module;
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poetteringstatic apr_status_t hm_listen(hm_ctx_t *ctx)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rv = apr_socket_create(&ctx->sock, ctx->mcast_addr->family,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "Heartmonitor: Failed to create listening socket.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rv = apr_socket_opt_set(ctx->sock, APR_SO_REUSEADDR, 1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "Heartmonitor: Failed to set APR_SO_REUSEADDR to 1 on socket.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rv = apr_socket_opt_set(ctx->sock, APR_SO_NONBLOCK, 1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering "Heartmonitor: Failed to set APR_SO_REUSEADDR to 1 on socket.");
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering rv = apr_socket_bind(ctx->sock, ctx->mcast_addr);
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering "Heartmonitor: Failed to bind on socket.");
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering rv = apr_mcast_join(ctx->sock, ctx->mcast_addr, NULL, NULL);
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering "Heartmonitor: Failed to join multicast group");
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering "Heartmonitor: Failed to accept localhost mulitcast on socket.");
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poetteringstatic void qs_to_table(const char *input, apr_table_t *parms,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering key = apr_strtok(query_string, "&", &strtok_state);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *value = '\0'; /* Split the string in two */
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering "Found query arg: %s = %s", key, value);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering key = apr_strtok(NULL, "&", &strtok_state);
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poetteringstatic apr_status_t hm_update_stats(hm_ctx_t *ctx, apr_pool_t *p)
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering char *path = apr_pstrcat(p, ctx->storage_path, ".tmp.XXXXXX", NULL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* TODO: Update stats file (!) */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rv = apr_file_mktemp(&fp, path, APR_CREATE | APR_WRITE, p);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering "Heartmonitor: Unable to open tmp file: %s", path);
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering for (hi = apr_hash_first(p, ctx->servers);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering apr_hash_this(hi, NULL, NULL, (void **) &s);
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering * Skip this entry from the heartbeat file -- when it comes back,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * we will reuse the memory...
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering apr_file_printf(fp, "%s &ready=%u&busy=%u&lastseen=%u\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "Heartmonitor: Unable to flush file: %s", path);
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering "Heartmonitor: Unable to close file: %s", path);
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering "Heartmonitor: Unable to set file permssions on %s",
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering rv = apr_file_rename(path, ctx->storage_path, p);
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering "Heartmonitor: Unable to move file: %s -> %s", path,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poetteringstatic hm_server_t *hm_get_server(hm_ctx_t *ctx, const char *ip)
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering s = apr_hash_get(ctx->servers, ip, APR_HASH_KEY_STRING);
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering s = apr_palloc(ctx->p, sizeof(hm_server_t));
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering apr_hash_set(ctx->servers, s->ip, APR_HASH_KEY_STRING, s);
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering/* Process a message receive from a backend node */
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poetteringstatic void hm_processmsg(hm_ctx_t *ctx, apr_pool_t *p,
5d6a86d7a034a1fb3d6e3f1b58e2c13739270894Lennart Poettering apr_sockaddr_t *from, char *buf, int len)
20ad4cfd8e5592f634f20468798cbc1055ab9fafZbigniew Jędrzejewski-Szmek /* TODO: REMOVE ME BEFORE PRODUCTION (????) */
20ad4cfd8e5592f634f20468798cbc1055ab9fafZbigniew Jędrzejewski-Szmek ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ctx->s,
20ad4cfd8e5592f634f20468798cbc1055ab9fafZbigniew Jędrzejewski-Szmek "Heartmonitor: %pI busy=%s ready=%s", from,
20ad4cfd8e5592f634f20468798cbc1055ab9fafZbigniew Jędrzejewski-Szmek apr_table_get(tbl, "busy"), apr_table_get(tbl, "ready"));
20ad4cfd8e5592f634f20468798cbc1055ab9fafZbigniew Jędrzejewski-Szmek apr_sockaddr_ip_get(&ip, from);
20ad4cfd8e5592f634f20468798cbc1055ab9fafZbigniew Jędrzejewski-Szmek s->busy = atoi(apr_table_get(tbl, "busy"));
20ad4cfd8e5592f634f20468798cbc1055ab9fafZbigniew Jędrzejewski-Szmek s->ready = atoi(apr_table_get(tbl, "ready"));
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ctx->s,
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering "Heartmonitor: malformed message from %pI",
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering/* Read message from multicast socket */
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poetteringstatic apr_status_t hm_recv(hm_ctx_t *ctx, apr_pool_t *p)
return APR_SUCCESS;
else if (rv) {
return rv;
return rv;
return rv;
switch (state) {
if (rv) {
apr_pool_t *p;
pfd.p = p;
apr_pool_destroy(p);
apr_pool_destroy(p);
return rv;
return OK;
if (rv) {
return !OK;
ctx,
if (rv) {
return !OK;
return OK;
char *buf;
return DECLINED;
return HTTP_METHOD_NOT_ALLOWED;
status = ap_get_brigade(r->input_filters, input_brigade, AP_MODE_READBYTES, APR_BLOCK_READ, MAX_MSG_LEN);
return HTTP_INTERNAL_SERVER_ERROR;
return HTTP_OK;
ctx->s = s;
return ctx;
return err;
return NULL;
char *host_str;
char *scope_id;
return err;
if (rv) {
if (port == 0) {
if (rv) {
return NULL;
{NULL}