Apache HTTPD
mod_heartmonitor.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "httpd.h"
18#include "http_config.h"
19#include "http_log.h"
20#include "http_core.h"
21#include "http_protocol.h"
22#include "apr_strings.h"
23#include "apr_hash.h"
24#include "apr_time.h"
25#include "ap_mpm.h"
26#include "scoreboard.h"
27#include "mod_watchdog.h"
28#include "ap_slotmem.h"
29#include "heartbeat.h"
30
31
32#ifndef HM_UPDATE_SEC
33/* How often we update the stats file */
34/* TODO: Make a runtime config */
35#define HM_UPDATE_SEC (5)
36#endif
37
38#define HM_WATHCHDOG_NAME ("_heartmonitor_")
39
42static int maxworkers = 10;
43
44module AP_MODULE_DECLARE_DATA heartmonitor_module;
45
46typedef struct hm_server_t
47{
48 const char *ip;
49 int busy;
50 int ready;
51 unsigned int port;
54
69
75
77{
78 apr_status_t rv;
79
80 rv = apr_socket_create(&ctx->sock, ctx->mcast_addr->family,
82
83 if (rv) {
85 "Failed to create listening socket.");
86 return rv;
87 }
88
90 if (rv) {
92 "Failed to set APR_SO_REUSEADDR to 1 on socket.");
93 return rv;
94 }
95
96
98 if (rv) {
100 "Failed to set APR_SO_NONBLOCK to 1 on socket.");
101 return rv;
102 }
103
104 rv = apr_socket_bind(ctx->sock, ctx->mcast_addr);
105 if (rv) {
107 "Failed to bind on socket.");
108 return rv;
109 }
110
111 rv = apr_mcast_join(ctx->sock, ctx->mcast_addr, NULL, NULL);
112
113 if (rv) {
115 "Failed to join multicast group");
116 return rv;
117 }
118
119 rv = apr_mcast_loopback(ctx->sock, 1);
120 if (rv) {
122 "Failed to accept localhost mulitcast on socket.");
123 return rv;
124 }
125
126 return APR_SUCCESS;
127}
128
129/* XXX: The same exists in mod_lbmethod_heartbeat.c where it is named argstr_to_table */
130static void qs_to_table(const char *input, apr_table_t *parms,
131 apr_pool_t *p)
132{
133 char *key;
134 char *value;
135 char *query_string;
136 char *strtok_state;
137
138 if (input == NULL) {
139 return;
140 }
141
143
145 while (key) {
146 value = strchr(key, '=');
147 if (value) {
148 *value = '\0'; /* Split the string in two */
149 value++; /* Skip passed the = */
150 }
151 else {
152 value = "1";
153 }
157 /*
158 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03182)
159 "Found query arg: %s = %s", key, value);
160 */
162 }
163}
164
165
166#define SEEN_TIMEOUT (30)
167
168/* Store in the slotmem */
170{
173 hm_server_t *new = s->s;
174 if (strcmp(old->ip, new->ip)==0) {
175 s->found = 1;
176 old->busy = new->busy;
177 old->ready = new->ready;
178 old->seen = new->seen;
179 }
180 return APR_SUCCESS;
181}
182/* Read the id corresponding to the entry in the slotmem */
184{
187 hm_server_t *new = s->s;
188 if (strcmp(old->ip, new->ip)==0) {
189 s->found = 1;
190 s->item_id = old->id;
191 }
192 return APR_SUCCESS;
193}
194/* update the entry or create it if not existing */
196{
197 /* We call do_all (to try to update) otherwise grab + put */
199 ctx.s = s;
200 ctx.found = 0;
202 if (!ctx.found) {
203 unsigned int i;
205 memset(&hmserver, 0, sizeof(hmserver));
206 apr_cpystrn(hmserver.ip, s->ip, sizeof(hmserver.ip));
207 hmserver.busy = s->busy;
208 hmserver.ready = s->ready;
209 hmserver.seen = s->seen;
210 /* XXX locking for grab() / put() */
211 storage->grab(slotmem, &i);
212 hmserver.id = i;
213 storage->put(slotmem, i, (unsigned char *)&hmserver, sizeof(hmserver));
214 }
215 return APR_SUCCESS;
216}
218{
220 ctx.s = s;
221 ctx.found = 0;
223 if (ctx.found) {
224 storage->release(slotmem, ctx.item_id);
225 }
226 return APR_SUCCESS;
227}
229{
230 apr_status_t rv;
231 apr_file_t *fp;
232 apr_file_t *fpin;
236 int updated = 0;
237 char *path = apr_pstrcat(pool, ctx->storage_path, ".tmp.XXXXXX", NULL);
238
239
240 /* TODO: Update stats file (!) */
242
243 if (rv) {
245 "Unable to open tmp file: %s", path);
246 return rv;
247 }
248 rv = apr_file_open(&fpin, ctx->storage_path, APR_READ|APR_BINARY|APR_BUFFERED,
250
251 now = apr_time_now();
252 if (rv == APR_SUCCESS) {
253 char *t;
257 apr_bucket_brigade *tmpbb;
258
260 if (rv) {
262 "Unable to read file: %s", ctx->storage_path);
263 return rv;
264 }
265
266 /* Read the file and update the line corresponding to the node */
269 apr_brigade_insert_file(bb, fpin, 0, fi.size, pool);
270 tmpbb = apr_brigade_create(pool, ba);
271 fage = apr_time_sec(now - fi.mtime);
272 do {
273 char buf[4096];
274 const char *ip;
275 apr_size_t bsize = sizeof(buf);
276
277 apr_brigade_cleanup(tmpbb);
278 if (APR_BRIGADE_EMPTY(bb)) {
279 break;
280 }
281 rv = apr_brigade_split_line(tmpbb, bb,
282 APR_BLOCK_READ, sizeof(buf));
283
284 if (rv) {
286 "Unable to read from file: %s", ctx->storage_path);
287 return rv;
288 }
289
290 apr_brigade_flatten(tmpbb, buf, &bsize);
291 if (bsize == 0) {
292 break;
293 }
294 buf[bsize - 1] = 0;
295 t = strchr(buf, ' ');
296 if (t) {
297 ip = apr_pstrmemdup(pool, buf, t - buf);
298 }
299 else {
300 ip = NULL;
301 }
302
303 if (!ip || buf[0] == '#') {
304 /* copy things we can't process */
305 apr_file_printf(fp, "%s\n", buf);
306 }
307 else if (strcmp(ip, s->ip) != 0 ) {
308 hm_server_t node;
309 apr_time_t seen;
310 const char *val;
311
312 /* Update seen time according to the last file modification */
315 if ((val = apr_table_get(hbt, "busy"))) {
316 node.busy = atoi(val);
317 }
318 else {
319 node.busy = 0;
320 }
321
322 if ((val = apr_table_get(hbt, "ready"))) {
323 node.ready = atoi(val);
324 }
325 else {
326 node.ready = 0;
327 }
328
329 if ((val = apr_table_get(hbt, "lastseen"))) {
330 node.seen = atoi(val);
331 }
332 else {
333 node.seen = SEEN_TIMEOUT;
334 }
335 seen = fage + node.seen;
336
337 if ((val = apr_table_get(hbt, "port"))) {
338 node.port = atoi(val);
339 }
340 else {
341 node.port = 80;
342 }
343 apr_file_printf(fp, "%s &ready=%u&busy=%u&lastseen=%u&port=%u\n",
344 ip, node.ready, node.busy, (unsigned int) seen, node.port);
345 }
346 else {
347 apr_time_t seen;
348 seen = apr_time_sec(now - s->seen);
349 apr_file_printf(fp, "%s &ready=%u&busy=%u&lastseen=%u&port=%u\n",
350 s->ip, s->ready, s->busy, (unsigned int) seen, s->port);
351 updated = 1;
352 }
353 } while (1);
354 }
355
356 if (!updated) {
357 apr_time_t seen;
358 seen = apr_time_sec(now - s->seen);
359 apr_file_printf(fp, "%s &ready=%u&busy=%u&lastseen=%u&port=%u\n",
360 s->ip, s->ready, s->busy, (unsigned int) seen, s->port);
361 }
362
363 rv = apr_file_flush(fp);
364 if (rv) {
366 "Unable to flush file: %s", path);
367 return rv;
368 }
369
370 rv = apr_file_close(fp);
371 if (rv) {
373 "Unable to close file: %s", path);
374 return rv;
375 }
376
380 if (rv && rv != APR_INCOMPLETE && rv != APR_ENOTIMPL) {
382 "Unable to set file permissions on %s",
383 path);
384 return rv;
385 }
386
387 rv = apr_file_rename(path, ctx->storage_path, pool);
388
389 if (rv) {
391 "Unable to move file: %s -> %s", path,
392 ctx->storage_path);
393 return rv;
394 }
395
396 return APR_SUCCESS;
397}
399{
400 if (slotmem)
402 else
403 return hm_file_update_stat(ctx, s, pool);
404}
405
406/* Store in a file */
408{
409 apr_status_t rv;
410 apr_file_t *fp;
413 char *path = apr_pstrcat(p, ctx->storage_path, ".tmp.XXXXXX", NULL);
414 /* TODO: Update stats file (!) */
416
417 if (rv) {
419 "Unable to open tmp file: %s", path);
420 return rv;
421 }
422
423 now = apr_time_now();
424 for (hi = apr_hash_first(p, ctx->servers);
425 hi != NULL; hi = apr_hash_next(hi)) {
426 hm_server_t *s = NULL;
427 apr_time_t seen;
428 apr_hash_this(hi, NULL, NULL, (void **) &s);
429 seen = apr_time_sec(now - s->seen);
430 if (seen > SEEN_TIMEOUT) {
431 /*
432 * Skip this entry from the heartbeat file -- when it comes back,
433 * we will reuse the memory...
434 */
435 }
436 else {
437 apr_file_printf(fp, "%s &ready=%u&busy=%u&lastseen=%u&port=%u\n",
438 s->ip, s->ready, s->busy, (unsigned int) seen, s->port);
439 }
440 }
441
442 rv = apr_file_flush(fp);
443 if (rv) {
445 "Unable to flush file: %s", path);
446 return rv;
447 }
448
449 rv = apr_file_close(fp);
450 if (rv) {
452 "Unable to close file: %s", path);
453 return rv;
454 }
455
459 if (rv && rv != APR_INCOMPLETE && rv != APR_ENOTIMPL) {
461 "Unable to set file permissions on %s",
462 path);
463 return rv;
464 }
465
466 rv = apr_file_rename(path, ctx->storage_path, p);
467
468 if (rv) {
470 "Unable to move file: %s -> %s", path,
471 ctx->storage_path);
472 return rv;
473 }
474
475 return APR_SUCCESS;
476}
477/* Store in a slotmem */
479{
480 apr_status_t rv;
483 now = apr_time_now();
484 for (hi = apr_hash_first(p, ctx->servers);
485 hi != NULL; hi = apr_hash_next(hi)) {
486 hm_server_t *s = NULL;
487 apr_time_t seen;
488 apr_hash_this(hi, NULL, NULL, (void **) &s);
489 seen = apr_time_sec(now - s->seen);
490 if (seen > SEEN_TIMEOUT) {
491 /* remove it */
493 } else {
494 /* update it */
496 }
497 if (rv !=APR_SUCCESS)
498 return rv;
499 }
500 return APR_SUCCESS;
501}
502/* Store/update the stats */
504{
505 if (slotmem)
507 else
508 return hm_file_update_stats(ctx, p);
509}
510
511static hm_server_t *hm_get_server(hm_ctx_t *ctx, const char *ip, const int port)
512{
513 hm_server_t *s;
514
515 s = apr_hash_get(ctx->servers, ip, APR_HASH_KEY_STRING);
516
517 if (s == NULL) {
518 s = apr_palloc(ctx->p, sizeof(hm_server_t));
519 s->ip = apr_pstrdup(ctx->p, ip);
520 s->port = port;
521 s->ready = 0;
522 s->busy = 0;
523 s->seen = 0;
524 apr_hash_set(ctx->servers, s->ip, APR_HASH_KEY_STRING, s);
525 }
526
527 return s;
528}
529
530/* Process a message received from a backend node */
532 apr_sockaddr_t *from, char *buf, apr_size_t len)
533{
535
536 buf[len] = '\0';
537
538 tbl = apr_table_make(p, 10);
539
540 qs_to_table(buf, tbl, p);
541
542 if (apr_table_get(tbl, "v") != NULL &&
543 apr_table_get(tbl, "busy") != NULL &&
544 apr_table_get(tbl, "ready") != NULL) {
545 char *ip;
546 int port = 80;
547 hm_server_t *s;
548 /* TODO: REMOVE ME BEFORE PRODUCTION (????) */
550 "%pI busy=%s ready=%s", from,
551 apr_table_get(tbl, "busy"), apr_table_get(tbl, "ready"));
552
553 apr_sockaddr_ip_get(&ip, from);
554
555 if (apr_table_get(tbl, "port") != NULL)
556 port = atoi(apr_table_get(tbl, "port"));
557
558 s = hm_get_server(ctx, ip, port);
559
560 s->busy = atoi(apr_table_get(tbl, "busy"));
561 s->ready = atoi(apr_table_get(tbl, "ready"));
562 s->seen = apr_time_now();
563 }
564 else {
566 "malformed message from %pI",
567 from);
568 }
569
570}
571/* Read message from multicast socket */
572#define MAX_MSG_LEN (1000)
574{
575 char buf[MAX_MSG_LEN + 1];
576 apr_sockaddr_t from;
578 apr_status_t rv;
579
580 from.pool = p;
581
582 rv = apr_socket_recvfrom(&from, ctx->sock, 0, buf, &len);
583
584 if (APR_STATUS_IS_EAGAIN(rv)) {
585 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s, APLOGNO(02088) "would block");
586 return APR_SUCCESS;
587 }
588 else if (rv) {
589 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ctx->s, APLOGNO(02089) "recvfrom failed");
590 return rv;
591 }
592
593 hm_processmsg(ctx, p, &from, buf, len);
594
595 return rv;
596}
597
598static apr_status_t hm_watchdog_callback(int state, void *data,
600{
604
605 if (!ctx->active) {
606 return rv;
607 }
608
609 switch (state) {
611 rv = hm_listen(ctx);
612 if (rv) {
613 ctx->status = rv;
615 "Unable to listen for connections!");
616 }
617 else {
618 ctx->keep_running = 1;
620 "%s listener started.",
622 }
623 break;
625 /* store in the slotmem or in the file depending on configuration */
628
629 while ((now - cur) < apr_time_sec(ctx->interval)) {
630 int n;
632 apr_pool_t *p;
633 apr_pollfd_t pfd;
635
637 apr_pool_tag(p, "hm_running");
638
640 pfd.desc.s = ctx->sock;
641 pfd.p = p;
642 pfd.reqevents = APR_POLLIN;
643
645
646 rc = apr_poll(&pfd, 1, &n, timeout);
647
648 if (!ctx->keep_running) {
650 break;
651 }
652 if (rc == APR_SUCCESS && (pfd.rtnevents & APR_POLLIN)) {
653 hm_recv(ctx, p);
654 }
657 }
658 break;
661 "stopping %s listener.",
663
664 ctx->keep_running = 0;
665 if (ctx->sock) {
666 apr_socket_close(ctx->sock);
667 ctx->sock = NULL;
668 }
669 break;
670 }
671 return rv;
672}
673
675 apr_pool_t *ptemp, server_rec *s)
676{
677 apr_status_t rv;
678 hm_ctx_t *ctx = ap_get_module_config(s->module_config,
679 &heartmonitor_module);
682
687 "mod_watchdog is required");
688 return !OK;
689 }
690
691 /* Create the slotmem */
693 /* this is the real thing */
694 if (maxworkers) {
697 if (!storage) {
699 "failed to lookup provider 'shm' for '%s', "
700 "maybe you need to load mod_slotmem_shm?",
702 return !OK;
703 }
704 storage->create(&slotmem, "mod_heartmonitor", sizeof(hm_slot_server_t), maxworkers, AP_SLOTMEM_TYPE_PREGRAB, p);
705 if (!slotmem) {
707 "slotmem_create for status failed");
708 return !OK;
709 }
710 }
711 }
712
713 if (!ctx->active) {
714 return OK;
715 }
716 rv = hm_watchdog_get_instance(&ctx->watchdog,
718 0, 1, p);
719 if (rv) {
721 "Failed to create watchdog instance (%s)",
723 return !OK;
724 }
725 /* Register a callback with zero interval. */
726 rv = hm_watchdog_register_callback(ctx->watchdog,
727 0,
728 ctx,
730 if (rv) {
732 "Failed to register watchdog callback (%s)",
734 return !OK;
735 }
737 "wd callback %s", HM_WATHCHDOG_NAME);
738 return OK;
739}
740
742{
743 apr_bucket_brigade *input_brigade;
745 char *buf;
749 char *ip;
750 hm_ctx_t *ctx;
751
752 if (strcmp(r->handler, "heartbeat")) {
753 return DECLINED;
754 }
755 if (r->method_number != M_POST) {
757 }
758
761 &heartmonitor_module);
762
766 if (status != APR_SUCCESS) {
768 }
769 apr_brigade_flatten(input_brigade, buf, &len);
770
771 /* we can't use hm_processmsg because it uses hm_get_server() */
772 buf[len] = '\0';
773 tbl = apr_table_make(r->pool, 10);
776 hmserver.ip = ip;
777 hmserver.port = 80;
778 if (apr_table_get(tbl, "port") != NULL)
779 hmserver.port = atoi(apr_table_get(tbl, "port"));
780 hmserver.busy = atoi(apr_table_get(tbl, "busy"));
781 hmserver.ready = atoi(apr_table_get(tbl, "ready"));
782 hmserver.seen = apr_time_now();
784
785 ap_set_content_type_ex(r, "text/plain", 1);
787 ap_rputs("OK", r);
788 ap_rflush(r);
789
790 return OK;
791}
792
794{
795 static const char * const aszSucc[]={ "mod_proxy.c", NULL };
797
799}
800
802{
803 hm_ctx_t *ctx = (hm_ctx_t *) apr_palloc(p, sizeof(hm_ctx_t));
804
805 ctx->active = 0;
807 /* TODO: Add directive for tuning the update interval
808 */
810 ctx->s = s;
811 apr_pool_create(&ctx->p, p);
812 apr_pool_tag(ctx->p, "hm_ctx");
813 ctx->servers = apr_hash_make(ctx->p);
814
815 return ctx;
816}
817
818static const char *cmd_hm_storage(cmd_parms *cmd,
819 void *dconf, const char *path)
820{
821 apr_pool_t *p = cmd->pool;
822 hm_ctx_t *ctx =
823 (hm_ctx_t *) ap_get_module_config(cmd->server->module_config,
824 &heartmonitor_module);
825 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
826
827 if (err != NULL) {
828 return err;
829 }
830
831 ctx->storage_path = ap_runtime_dir_relative(p, path);
832
833 return NULL;
834}
835
836static const char *cmd_hm_listen(cmd_parms *cmd,
837 void *dconf, const char *mcast_addr)
838{
839 apr_status_t rv;
840 char *host_str;
841 char *scope_id;
842 apr_port_t port = 0;
843 apr_pool_t *p = cmd->pool;
844 hm_ctx_t *ctx =
845 (hm_ctx_t *) ap_get_module_config(cmd->server->module_config,
846 &heartmonitor_module);
847 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
848
849 if (err != NULL) {
850 return err;
851 }
852
853 if (!ctx->active) {
854 ctx->active = 1;
855 }
856 else {
857 return "HeartbeatListen: May only be specified once.";
858 }
859
860 rv = apr_parse_addr_port(&host_str, &scope_id, &port, mcast_addr, cmd->temp_pool);
861
862 if (rv) {
863 return "HeartbeatListen: Unable to parse multicast address.";
864 }
865
866 if (host_str == NULL) {
867 return "HeartbeatListen: No host provided in multicast address";
868 }
869
870 if (port == 0) {
871 return "HeartbeatListen: No port provided in multicast address";
872 }
873
874 rv = apr_sockaddr_info_get(&ctx->mcast_addr, host_str, APR_INET, port, 0,
875 p);
876
877 if (rv) {
878 return
879 "HeartbeatListen: apr_sockaddr_info_get failed on multicast address";
880 }
881
882 return NULL;
883}
884
885static const char *cmd_hm_maxworkers(cmd_parms *cmd,
886 void *dconf, const char *data)
887{
888 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
889
890 if (err != NULL) {
891 return err;
892 }
893
895 if (maxworkers != 0 && maxworkers < 10)
896 return "HeartbeatMaxServers: Should be 0 for file storage, "
897 "or greater or equal than 10 for slotmem";
898
899 return NULL;
900}
901
902static const command_rec hm_cmds[] = {
903 AP_INIT_TAKE1("HeartbeatListen", cmd_hm_listen, NULL, RSRC_CONF,
904 "Address to listen for heartbeat requests"),
905 AP_INIT_TAKE1("HeartbeatStorage", cmd_hm_storage, NULL, RSRC_CONF,
906 "Path to store heartbeat data."),
907 AP_INIT_TAKE1("HeartbeatMaxServers", cmd_hm_maxworkers, NULL, RSRC_CONF,
908 "Max number of servers when using slotmem (instead file) to store heartbeat data."),
909 {NULL}
910};
911
914 NULL, /* create per-directory config structure */
915 NULL, /* merge per-directory config structures */
916 hm_create_config, /* create per-server config structure */
917 NULL, /* merge per-server config structures */
918 hm_cmds, /* command apr_table_t */
920};
Apache Multi-Processing Module library.
int n
Definition ap_regex.h:278
const char apr_size_t len
Definition ap_regex.h:187
Memory Slot Extension Storage Module for Apache.
APR Hash Tables.
APR Strings library.
APR Time Library.
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
char * ap_runtime_dir_relative(apr_pool_t *p, const char *fname)
Definition config.c:1610
#define ap_get_module_config(v, m)
void ap_hook_post_config(ap_HOOK_post_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:105
#define AP_DECLARE_MODULE(foo)
void ap_hook_handler(ap_HOOK_handler_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:170
request_rec int int apr_table_t const char * path
request_rec * r
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
apr_status_t ap_get_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes)
int ap_state_query(int query_code)
Definition core.c:5378
#define AP_SQ_MS_CREATE_CONFIG
Definition http_core.h:1051
#define AP_SQ_MAIN_STATE
Definition http_core.h:1030
#define APLOGNO(n)
Definition http_log.h:117
#define ap_log_error
Definition http_log.h:370
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_CRIT
Definition http_log.h:66
#define APLOG_EMERG
Definition http_log.h:64
#define APLOG_DEBUG
Definition http_log.h:71
const unsigned char * buf
Definition util_md5.h:50
int int ap_rflush(request_rec *r)
Definition protocol.c:2253
int ap_map_http_request_error(apr_status_t rv, int status)
void ap_set_content_length(request_rec *r, apr_off_t length)
Definition protocol.c:160
static APR_INLINE int ap_rputs(const char *str, request_rec *r)
void ap_set_content_type_ex(request_rec *r, const char *ct, int trusted)
void * ap_lookup_provider(const char *provider_group, const char *provider_name, const char *provider_version)
Definition provider.c:99
const char apr_port_t port
Definition http_vhost.h:125
#define APR_INCOMPLETE
Definition apr_errno.h:452
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_STATUS_IS_EAGAIN(s)
Definition apr_errno.h:1272
#define APR_BRIGADE_EMPTY(b)
apr_brigade_flush void * ctx
@ APR_BLOCK_READ
Definition apr_buckets.h:58
const char *const const char *const * aszSucc
Definition apr_hooks.h:346
#define APR_HOOK_FIRST
Definition apr_hooks.h:301
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
#define APR_RETRIEVE_OPTIONAL_FN(name)
#define APR_OPTIONAL_FN_TYPE(name)
apr_redis_t * rc
Definition apr_redis.h:173
#define RSRC_CONF
#define DEFAULT_HEARTBEAT_STORAGE
Definition heartbeat.h:53
#define HTTP_BAD_REQUEST
Definition httpd.h:508
#define HTTP_METHOD_NOT_ALLOWED
Definition httpd.h:513
#define APR_PROTO_UDP
#define AP_SLOTMEM_PROVIDER_GROUP
Definition ap_slotmem.h:52
#define AP_SLOTMEM_TYPE_PREGRAB
Definition ap_slotmem.h:72
#define AP_SLOTMEM_PROVIDER_VERSION
Definition ap_slotmem.h:53
#define AP_WATCHDOG_STATE_STARTING
#define AP_WATCHDOG_STATE_STOPPING
#define AP_WATCHDOG_STATE_RUNNING
#define M_POST
Definition httpd.h:594
#define STANDARD20_MODULE_STUFF
int ap_unescape_url(char *url)
Definition util.c:1939
#define GLOBAL_ONLY
const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden)
Definition core.c:1301
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
const char int apr_pool_t * pool
Definition apr_cstr.h:84
const char * input
Definition apr_cstr.h:93
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
const char * key
void * data
#define APR_READ
Definition apr_file_io.h:93
#define APR_BINARY
Definition apr_file_io.h:98
#define APR_WRITE
Definition apr_file_io.h:94
#define APR_BUFFERED
#define APR_CREATE
Definition apr_file_io.h:95
#define APR_FPROT_WREAD
#define APR_FPROT_GREAD
#define APR_OS_DEFAULT
#define APR_FPROT_UREAD
#define APR_FINFO_MTIME
#define APR_FINFO_SIZE
#define APR_HASH_KEY_STRING
Definition apr_hash.h:47
apr_interval_time_t t
apr_uint16_t apr_port_t
#define APR_INET
char ** scope_id
@ APR_POLL_SOCKET
Definition apr_poll.h:93
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
void * mem
#define APR_SO_REUSEADDR
#define APR_SO_NONBLOCK
const char * s
Definition apr_strings.h:95
apr_int32_t apr_int32_t apr_int32_t err
apr_cmdtype_e cmd
int int status
apr_int64_t apr_interval_time_t
Definition apr_time.h:55
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_sec(time)
Definition apr_time.h:63
#define apr_time_from_sec(sec)
Definition apr_time.h:78
#define APR_POLLIN
Definition apr_poll.h:49
commun structures for mod_heartmonitor.c and mod_lbmethod_heartbeat.c
Apache Configuration.
CORE HTTP Daemon.
Apache Logging library.
HTTP protocol handling.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
static apr_status_t hm_recv(hm_ctx_t *ctx, apr_pool_t *p)
static const char * cmd_hm_storage(cmd_parms *cmd, void *dconf, const char *path)
static int maxworkers
static void qs_to_table(const char *input, apr_table_t *parms, apr_pool_t *p)
static void hm_processmsg(hm_ctx_t *ctx, apr_pool_t *p, apr_sockaddr_t *from, char *buf, apr_size_t len)
static apr_status_t hm_update_stats(hm_ctx_t *ctx, apr_pool_t *p)
static apr_status_t hm_slotmem_update_stats(hm_ctx_t *ctx, apr_pool_t *p)
static hm_server_t * hm_get_server(hm_ctx_t *ctx, const char *ip, const int port)
#define HM_WATHCHDOG_NAME
static apr_status_t hm_update_stat(hm_ctx_t *ctx, hm_server_t *s, apr_pool_t *pool)
static int hm_handler(request_rec *r)
static const char * cmd_hm_maxworkers(cmd_parms *cmd, void *dconf, const char *data)
static const ap_slotmem_provider_t * storage
static const command_rec hm_cmds[]
static int hm_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
#define MAX_MSG_LEN
static apr_status_t hm_slotmem_remove_stat(hm_server_t *s, apr_pool_t *pool)
static apr_status_t hm_file_update_stat(hm_ctx_t *ctx, hm_server_t *s, apr_pool_t *pool)
static void hm_register_hooks(apr_pool_t *p)
static const char * cmd_hm_listen(cmd_parms *cmd, void *dconf, const char *mcast_addr)
static apr_status_t hm_watchdog_callback(int state, void *data, apr_pool_t *pool)
#define SEEN_TIMEOUT
static void * hm_create_config(apr_pool_t *p, server_rec *s)
static apr_status_t hm_readid(void *mem, void *data, apr_pool_t *p)
static apr_status_t hm_slotmem_update_stat(hm_server_t *s, apr_pool_t *pool)
#define HM_UPDATE_SEC
static ap_slotmem_instance_t * slotmem
static apr_status_t hm_file_update_stats(hm_ctx_t *ctx, apr_pool_t *p)
static apr_status_t hm_update(void *mem, void *data, apr_pool_t *p)
static apr_status_t hm_listen(hm_ctx_t *ctx)
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
static apr_status_t ap_watchdog_register_callback(ap_watchdog_t *w, apr_interval_time_t interval, const void *data, ap_watchdog_callback_fn_t *callback)
static apr_status_t ap_watchdog_get_instance(ap_watchdog_t **watchdog, const char *name, int parent, int singleton, apr_pool_t *p)
Watchdog module for Apache.
Apache scoreboard library.
apr_status_t(* create)(ap_slotmem_instance_t **inst, const char *name, apr_size_t item_size, unsigned int item_num, ap_slotmem_type_t type, apr_pool_t *pool)
Definition ap_slotmem.h:111
apr_status_t(* doall)(ap_slotmem_instance_t *s, ap_slotmem_callback_fn_t *func, void *data, apr_pool_t *pool)
Definition ap_slotmem.h:99
apr_status_t(* put)(ap_slotmem_instance_t *slot, unsigned int item_id, unsigned char *src, apr_size_t src_len)
Definition ap_slotmem.h:148
apr_status_t(* release)(ap_slotmem_instance_t *s, unsigned int item_id)
Definition ap_slotmem.h:182
apr_status_t(* grab)(ap_slotmem_instance_t *s, unsigned int *item_id)
Definition ap_slotmem.h:175
apr_int16_t reqevents
Definition apr_poll.h:111
apr_datatype_e desc_type
Definition apr_poll.h:110
apr_descriptor desc
Definition apr_poll.h:113
apr_pool_t * p
Definition apr_poll.h:109
apr_int16_t rtnevents
Definition apr_poll.h:112
apr_pool_t * pool
apr_sockaddr_t * client_addr
Definition httpd.h:1166
apr_pool_t * pool
Definition httpd.h:1154
struct apr_bucket_alloc_t * bucket_alloc
Definition httpd.h:1201
apr_status_t status
server_rec * s
volatile int keep_running
apr_interval_time_t interval
apr_hash_t * servers
apr_socket_t * sock
ap_watchdog_t * watchdog
apr_sockaddr_t * mcast_addr
const char * storage_path
apr_pool_t * p
apr_time_t seen
const char * ip
unsigned int port
A structure that represents the current request.
Definition httpd.h:845
const char * handler
Definition httpd.h:994
int method_number
Definition httpd.h:898
apr_pool_t * pool
Definition httpd.h:847
conn_rec * connection
Definition httpd.h:849
struct ap_filter_t * input_filters
Definition httpd.h:1072
server_rec * server
Definition httpd.h:851
A structure to store information for each virtual server.
Definition httpd.h:1322
struct ap_conf_vector_t * module_config
Definition httpd.h:1341
static apr_time_t now
Definition testtime.c:33
apr_socket_t * s
Definition apr_poll.h:101
apr_status_t apr_socket_recvfrom(apr_sockaddr_t *from, apr_socket_t *sock, apr_int32_t flags, char *buf, apr_size_t *len)
Definition sendrecv.c:146
apr_status_t apr_socket_bind(apr_socket_t *sock, apr_sockaddr_t *sa)
Definition sockets.c:216
apr_status_t apr_socket_close(apr_socket_t *thesocket)
Definition sockets.c:211
apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type, int protocol, apr_pool_t *cont)
Definition sockets.c:116
apr_status_t apr_socket_opt_set(apr_socket_t *sock, apr_int32_t opt, apr_int32_t on)
Definition sockopt.c:113
@ AP_MODE_READBYTES
Definition util_filter.h:43
IN ULONG IN INT timeout