root/src/modules/http.c

Revision e64e042f4c61e4e3c50af3639e028056d8bbfa88, 20.6 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 7 years ago)

fix up some apis, allow for firing checks only once

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #include "noit_defines.h"
7
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <errno.h>
11 #include <assert.h>
12 #include <math.h>
13
14 #include <libxml/parser.h>
15 #include <libxml/tree.h>
16 #include <libxml/xpath.h>
17
18 #include "noit_module.h"
19 #include "noit_poller.h"
20 #include "utils/noit_log.h"
21 #include "utils/noit_hash.h"
22
23 #include <apr_uri.h>
24 #include <apr_atomic.h>
25 #include <apr_strings.h>
26 #include "serf.h"
27
28 #define NOIT_HTTP_VERSION_STRING "0.1"
29
30 typedef struct {
31   noit_hash_table *options;
32   void (*results)(noit_module_t *, noit_check_t);
33 } serf_module_conf_t;
34
35 typedef struct {
36   int using_ssl;
37   serf_ssl_context_t *ssl_ctx;
38   serf_bucket_alloc_t *bkt_alloc;
39 } app_baton_t;
40
41 typedef struct {
42   serf_response_acceptor_t acceptor;
43   app_baton_t *acceptor_baton;
44
45   serf_response_handler_t handler;
46   const char *host;
47   const char *method;
48   const char *path;
49   const char *authn;
50
51   noit_module_t *self;
52   noit_check_t check;
53 } handler_baton_t;
54
55 typedef struct buf_t {
56   char *b;
57   int l;
58 } buf_t;
59
60 typedef struct {
61   apr_pool_t *pool;
62   apr_sockaddr_t *address;
63   serf_context_t *context;
64   serf_connection_t *connection;
65   serf_request_t *request;
66   app_baton_t app_ctx;
67   handler_baton_t handler_ctx;
68   apr_uri_t url;
69   int timed_out;
70
71   serf_status_line status;
72   buf_t headers;
73   buf_t body;
74
75   struct timeval finish_time;
76   eventer_t fd_event;
77   eventer_t timeout_event;
78 } serf_check_info_t;
79
80 typedef struct {
81   serf_check_info_t serf;
82   struct timeval xml_doc_time;
83   xmlDocPtr xml_doc;
84 } resmon_check_info_t;
85
86 typedef struct {
87   noit_module_t *self;
88   noit_check_t check;
89   void *serf_baton;
90   apr_socket_t *skt;
91 } serf_closure_t;
92
93 static noit_log_stream_t nlerr = NULL;
94 static noit_log_stream_t nldeb = NULL;
95 static int serf_handler(eventer_t e, int mask, void *closure,
96                         struct timeval *now);
97 static int serf_recur_handler(eventer_t e, int mask, void *closure,
98                               struct timeval *now);
99 static void serf_log_results(noit_module_t *self, noit_check_t check);
100 static void resmon_log_results(noit_module_t *self, noit_check_t check);
101
102 static int serf_config(noit_module_t *self, noit_hash_table *options) {
103   serf_module_conf_t *conf;
104   conf = calloc(1, sizeof(*conf));
105   conf->options = options;
106   conf->results = serf_log_results;
107   noit_module_set_userdata(self, conf);
108   return 0;
109 }
110 static int resmon_config(noit_module_t *self, noit_hash_table *options) {
111   serf_module_conf_t *conf;
112   conf = calloc(1, sizeof(*conf));
113   conf->options = options;
114   if(!conf->options) conf->options = calloc(1, sizeof(*conf->options));
115   noit_hash_store(conf->options, strdup("url"), strlen("url"),
116                   strdup("http://localhost:81/"));
117   conf->results = resmon_log_results;
118   noit_module_set_userdata(self, conf);
119   return 0;
120 }
121 static void generic_log_results(noit_module_t *self, noit_check_t check) {
122   serf_module_conf_t *module_conf;
123   module_conf = noit_module_get_userdata(self);
124   module_conf->results(self, check);
125 }
126 static void serf_log_results(noit_module_t *self, noit_check_t check) {
127   serf_check_info_t *ci = check->closure;
128   struct timeval duration;
129   stats_t current;
130   int expect_code = 200;
131   char *code_str;
132   char human_buffer[256], code[4], rt[14];
133
134   if(noit_hash_retrieve(check->config, "code", strlen("code"),
135                         (void **)&code_str))
136     expect_code = atoi(code_str);
137
138   sub_timeval(ci->finish_time, check->last_fire_time, &duration);
139
140   snprintf(code, sizeof(code), "%3d", ci->status.code);
141   snprintf(rt, sizeof(rt), "%.3fms",
142            (float)duration.tv_sec + (float)duration.tv_usec / 1000000.0);
143   snprintf(human_buffer, sizeof(human_buffer),
144            "code=%s,rt=%s,bytes=%d",
145            ci->status.code ? code : "undefined",
146            ci->timed_out ? "timeout" : rt,
147            ci->body.l);
148   noitL(nldeb, "http(%s) [%s]\n", check->target, human_buffer);
149
150   current.duration = duration.tv_sec * 1000 + duration.tv_usec / 1000;
151   current.available = (ci->timed_out || !ci->status.code) ? NP_UNAVAILABLE : NP_AVAILABLE;
152   current.state = (ci->status.code != 200) ? NP_BAD : NP_GOOD;
153   current.status = human_buffer;
154   noit_poller_set_state(check, &current);
155 }
156 static void resmon_log_results(noit_module_t *self, noit_check_t check) {
157   serf_check_info_t *ci = check->closure;
158   resmon_check_info_t *rci = check->closure;
159   struct timeval duration;
160   stats_t current;
161   int services = 0;
162   char human_buffer[256], rt[14];
163   xmlDocPtr resmon_results = NULL;
164   xmlXPathContextPtr xpath_ctxt = NULL;
165
166   if(ci->body.b) resmon_results = xmlParseMemory(ci->body.b, ci->body.l);
167   if(resmon_results) {
168     xmlXPathObjectPtr pobj;
169     xpath_ctxt = xmlXPathNewContext(resmon_results);
170     pobj = xmlXPathEval((xmlChar *)"/ResmonResults/ResmonResult", xpath_ctxt);
171     if(pobj)
172       if(pobj->type == XPATH_NODESET)
173         services = xmlXPathNodeSetGetLength(pobj->nodesetval);
174     xmlXPathFreeObject(pobj);
175   } else {
176     noitL(nlerr, "Error in resmon doc: %s\n", ci->body.b);
177   }
178   if(xpath_ctxt) xmlXPathFreeContext(xpath_ctxt);
179
180   /* Save out results for future dependent checks */
181   memcpy(&rci->xml_doc_time, &ci->finish_time, sizeof(ci->finish_time));
182   if(rci->xml_doc) xmlFreeDoc(rci->xml_doc);
183   rci->xml_doc = resmon_results;
184
185   sub_timeval(ci->finish_time, check->last_fire_time, &duration);
186
187   snprintf(rt, sizeof(rt), "%.3fms",
188            (float)duration.tv_sec + (float)duration.tv_usec / 1000000.0);
189   snprintf(human_buffer, sizeof(human_buffer),
190            "services=%d,rt=%s",
191            services,
192            ci->timed_out ? "timeout" : rt);
193   noitL(nldeb, "resmon(%s) [%s]\n", check->target, human_buffer);
194
195   current.duration = duration.tv_sec * 1000 + duration.tv_usec / 1000;
196   current.available = (ci->timed_out || ci->status.code != 200) ?
197                           NP_UNAVAILABLE : NP_AVAILABLE;
198   current.state = services ? NP_GOOD : NP_BAD;
199   current.status = human_buffer;
200   noit_poller_set_state(check, &current);
201 }
202 static int serf_complete(eventer_t e, int mask,
203                          void *closure, struct timeval *now) {
204   serf_closure_t *ccl = (serf_closure_t *)closure;
205   serf_check_info_t *ci = (serf_check_info_t *)ccl->check->closure;
206
207   noitLT(nldeb, now, "serf_complete(%s)\n", ccl->check->target);
208   generic_log_results(ccl->self, ccl->check);
209   if(ci->connection) {
210     serf_connection_close(ci->connection);
211     ci->connection = NULL;
212   }
213   if(ci->fd_event) {
214     eventer_remove_fd(ci->fd_event->fd);
215     eventer_free(ci->fd_event);
216     ci->fd_event = NULL;
217   }
218   ci->timeout_event = NULL;
219   apr_pool_destroy(ci->pool);
220   memset(ci, 0, sizeof(*ci));
221   ccl->check->flags &= ~NP_RUNNING;
222   free(ccl);
223   return 0;
224 }
225
226 static int serf_handler(eventer_t e, int mask,
227                         void *closure, struct timeval *now) {
228   apr_pollfd_t desc = { 0 };
229   serf_closure_t *sct = closure;
230   serf_check_info_t *ci = sct->check->closure;
231
232   desc.desc_type = APR_POLL_SOCKET;
233   desc.desc.s = sct->skt;
234
235   desc.rtnevents = 0;
236   if(mask & EVENTER_READ) desc.rtnevents |= APR_POLLIN;
237   if(mask & EVENTER_WRITE) desc.rtnevents |= APR_POLLOUT;
238   if(mask & EVENTER_EXCEPTION) desc.rtnevents |= APR_POLLERR;
239   serf_event_trigger(ci->context, sct->serf_baton, &desc);
240   serf_context_prerun(ci->context);
241
242   /* We're about to deschedule and free the event, drop our reference */
243   if(!e->mask)
244     ci->fd_event = NULL;
245
246   return e->mask;
247 }
248
249 static int serf_init(noit_module_t *self) {
250   return 0;
251 }
252 static void closed_connection(serf_connection_t *conn,
253                               void *closed_baton,
254                               apr_status_t why,
255                               apr_pool_t *pool) {
256 }
257
258 static serf_bucket_t* conn_setup(apr_socket_t *skt,
259                                 void *setup_baton,
260                                 apr_pool_t *pool) {
261   serf_bucket_t *c;
262   app_baton_t *ctx = setup_baton;
263
264   c = serf_bucket_socket_create(skt, ctx->bkt_alloc);
265   if (ctx->using_ssl) {
266       c = serf_bucket_ssl_decrypt_create(c, ctx->ssl_ctx, ctx->bkt_alloc);
267       if (!ctx->ssl_ctx) {
268           ctx->ssl_ctx = serf_bucket_ssl_decrypt_context_get(c);
269       }
270   }
271
272   return c;
273 }
274
275 static serf_bucket_t* accept_response(serf_request_t *request,
276                                       serf_bucket_t *stream,
277                                       void *acceptor_baton,
278                                       apr_pool_t *pool) {
279   serf_bucket_t *c;
280   serf_bucket_alloc_t *bkt_alloc;
281
282   /* get the per-request bucket allocator */
283   bkt_alloc = serf_request_get_alloc(request);
284
285   /* Create a barrier so the response doesn't eat us! */
286   c = serf_bucket_barrier_create(stream, bkt_alloc);
287
288   return serf_bucket_response_create(c, bkt_alloc);
289 }
290
291 static void append_buf(apr_pool_t *p, buf_t *b,
292                        const char *data, int len) {
293   char *n;
294   n = apr_palloc(p, b->l + len + 1);
295   if(b->l == 0)
296     b->b = n;
297   else {
298     memcpy(n, b->b, b->l);
299     b->b = n;
300   }
301   memcpy(b->b + b->l, data, len);
302   b->l += len;
303   b->b[b->l] = '\0';
304 }
305
306 static apr_status_t handle_response(serf_request_t *request,
307                                     serf_bucket_t *response,
308                                     void *handler_baton,
309                                     apr_pool_t *pool) {
310   const char *data;
311   apr_size_t len;
312   apr_status_t status;
313   handler_baton_t *ctx = handler_baton;
314   serf_check_info_t *ci = ctx->check->closure;
315
316   if(response == NULL) {
317     /* We were cancelled. */
318     goto finish;
319   }
320   status = serf_bucket_response_status(response, &ci->status);
321   if (status) {
322     if (APR_STATUS_IS_EAGAIN(status)) {
323       return status;
324     }
325     goto finish;
326   }
327
328   while (1) {
329     status = serf_bucket_read(response, 1024*32, &data, &len);
330     if (SERF_BUCKET_READ_ERROR(status))
331       return status;
332
333     append_buf(ci->pool, &ci->body, data, len);
334
335     /* are we done yet? */
336     if (APR_STATUS_IS_EOF(status)) {
337       serf_bucket_t *hdrs;
338       hdrs = serf_bucket_response_get_headers(response);
339       while (1) {
340         status = serf_bucket_read(hdrs, 2048, &data, &len);
341         if (SERF_BUCKET_READ_ERROR(status))
342           return status;
343
344         append_buf(ci->pool, &ci->headers, data, len);
345         if (APR_STATUS_IS_EOF(status)) {
346           break;
347         }
348       }
349
350       goto finish;
351     }
352
353     /* have we drained the response so far? */
354     if (APR_STATUS_IS_EAGAIN(status))
355       return status;
356
357     /* loop to read some more. */
358   }
359  finish:
360   gettimeofday(&ci->finish_time, NULL);
361   if(ci->timeout_event) {
362     eventer_remove(ci->timeout_event);
363     ci->timed_out = 0;
364     memcpy(&ci->timeout_event->whence, &ci->finish_time,
365            sizeof(&ci->finish_time));
366     eventer_add(ci->timeout_event);
367   }
368   return APR_EOF;
369 }
370
371 static apr_status_t setup_request(serf_request_t *request,
372                                   void *setup_baton,
373                                   serf_bucket_t **req_bkt,
374                                   serf_response_acceptor_t *acceptor,                                             void **acceptor_baton,
375                                   serf_response_handler_t *handler,
376                                   void **handler_baton,
377                                   apr_pool_t *pool) {
378   handler_baton_t *ctx = setup_baton;
379   serf_bucket_t *hdrs_bkt;
380   serf_bucket_t *body_bkt;
381
382   body_bkt = NULL;
383
384   *req_bkt = serf_bucket_request_create(ctx->method, ctx->path, body_bkt,
385                                         serf_request_get_alloc(request));
386
387   hdrs_bkt = serf_bucket_request_get_headers(*req_bkt);
388
389   serf_bucket_headers_setn(hdrs_bkt, "Host", ctx->host);
390   serf_bucket_headers_setn(hdrs_bkt, "User-Agent",
391                            "Noit/" NOIT_HTTP_VERSION_STRING);
392   /* Shouldn't serf do this for us? */
393   serf_bucket_headers_setn(hdrs_bkt, "Accept-Encoding", "gzip");
394
395   if (ctx->authn != NULL) {
396     serf_bucket_headers_setn(hdrs_bkt, "Authorization", ctx->authn);
397   }
398
399   if (ctx->acceptor_baton->using_ssl) {
400     serf_bucket_alloc_t *req_alloc;
401     app_baton_t *app_ctx = ctx->acceptor_baton;
402
403     req_alloc = serf_request_get_alloc(request);
404
405     if (app_ctx->ssl_ctx == NULL) {
406       *req_bkt =
407         serf_bucket_ssl_encrypt_create(*req_bkt, NULL,
408                                        app_ctx->bkt_alloc);
409       app_ctx->ssl_ctx =
410         serf_bucket_ssl_encrypt_context_get(*req_bkt);
411     }
412     else {
413       *req_bkt =
414         serf_bucket_ssl_encrypt_create(*req_bkt, app_ctx->ssl_ctx,
415                                        app_ctx->bkt_alloc);
416     }
417   }
418
419   *acceptor = ctx->acceptor;
420   *acceptor_baton = ctx->acceptor_baton;
421   *handler = ctx->handler;
422   *handler_baton = ctx;
423
424   return APR_SUCCESS;
425 }
426
427 struct __unix_apr_socket_t {
428   apr_pool_t *pool;
429   int socketdes;
430 };
431
432 static apr_status_t serf_eventer_add(void *user_baton,
433                                      apr_pollfd_t *pfd,
434                                      void *serf_baton) {
435   eventer_t e, newe = NULL;
436   serf_closure_t *sct = user_baton, *newsct;
437   assert(pfd->desc_type == APR_POLL_SOCKET);
438   struct __unix_apr_socket_t *hack = (struct __unix_apr_socket_t *)pfd->desc.s;
439
440   noitL(nldeb, "serf_eventer_add() => %d\n", hack->socketdes);
441   e = eventer_find_fd(hack->socketdes);
442   if(!e) {
443     newe = e = eventer_alloc();
444     e->fd = hack->socketdes;
445     e->callback = serf_handler;
446     e->closure = calloc(1, sizeof(serf_closure_t));
447   }
448   newsct = e->closure;
449   newsct->self = sct->self;
450   newsct->check = sct->check;
451   newsct->serf_baton = serf_baton;
452   newsct->skt = pfd->desc.s;
453   e->mask = 0;
454   if(pfd->reqevents & APR_POLLIN) e->mask |= EVENTER_READ;
455   if(pfd->reqevents & APR_POLLOUT) e->mask |= EVENTER_WRITE;
456   if(pfd->reqevents & APR_POLLERR) e->mask |= EVENTER_EXCEPTION;
457   if(newe) {
458     serf_check_info_t *ci = sct->check->closure;
459     eventer_add(newe);
460     ci->fd_event = newe;
461   }
462 /* ** Unneeded as this is called recursively **
463   else
464     eventer_update(e);
465 */
466   return APR_SUCCESS;
467 }
468 static apr_status_t serf_eventer_remove(void *user_baton,
469                                         apr_pollfd_t *pfd,
470                                         void *serf_baton) {
471   serf_closure_t *sct = user_baton;
472   serf_check_info_t *ci;
473   eventer_t e;
474
475   ci = sct->check->closure;
476   assert(pfd->desc_type == APR_POLL_SOCKET);
477   struct __unix_apr_socket_t *hack = (struct __unix_apr_socket_t *)pfd->desc.s;
478
479   noitL(nldeb, "serf_eventer_remove() => %d\n", hack->socketdes);
480   e = eventer_find_fd(hack->socketdes);
481   if(e) e->mask = 0;
482   return 0;
483 }
484
485 static int serf_initiate(noit_module_t *self, noit_check_t check) {
486   serf_closure_t *ccl;
487   serf_check_info_t *ci;
488   struct timeval when, p_int;
489   apr_status_t status;
490   eventer_t newe;
491   serf_module_conf_t *mod_config;
492   char *config_url;
493
494   mod_config = noit_module_get_userdata(self);
495   ci = (serf_check_info_t *)check->closure;
496   /* We cannot be running */
497   assert(!(check->flags & NP_RUNNING));
498   check->flags |= NP_RUNNING;
499   noitL(nldeb, "serf_initiate(%p,%s)\n",
500         self, check->target);
501
502   /* remove a timeout if we still have one -- we should unless someone
503    * has set a lower timeout than the period.
504    */
505   ci->timed_out = 1;
506   if(ci->timeout_event) {
507     eventer_remove(ci->timeout_event);
508     free(ci->timeout_event->closure);
509     eventer_free(ci->timeout_event);
510     ci->timeout_event = NULL;
511   }
512   assert(!ci->pool);
513   apr_pool_create(&ci->pool, NULL);
514   apr_atomic_init(ci->pool);
515
516   gettimeofday(&when, NULL);
517   memcpy(&check->last_fire_time, &when, sizeof(when));
518
519   ccl = apr_pcalloc(ci->pool, sizeof(*ccl));
520   ccl->self = self;
521   ccl->check = check;
522
523   if(!noit_hash_retrieve(check->config, "url", strlen("url"),
524                         (void **)&config_url))
525     if(!mod_config->options ||
526        !noit_hash_retrieve(mod_config->options, "url", strlen("url"),
527                            (void **)&config_url))
528       config_url = "http://localhost/";
529   apr_uri_parse(ci->pool, config_url, &ci->url);
530
531   if (!ci->url.port) {
532     ci->url.port = apr_uri_port_of_scheme(ci->url.scheme);
533   }
534   if (!ci->url.path) {
535     ci->url.path = "/";
536   }
537
538   if (strcasecmp(ci->url.scheme, "https") == 0) {
539     ci->app_ctx.using_ssl = 1;
540   }
541   else {
542     ci->app_ctx.using_ssl = 0;
543   }
544
545   status = apr_sockaddr_info_get(&ci->address,
546                                  check->target, APR_UNSPEC, ci->url.port, 0,
547                                  ci->pool);
548   if (status) {
549     /* Handle error -- log failure */
550     apr_pool_destroy(ci->pool);
551     memset(ci, 0, sizeof(*ci));
552     check->flags &= ~NP_RUNNING;
553     return 0;
554   }
555
556   ci->context = serf_context_create_ex(ccl, serf_eventer_add,
557                                        serf_eventer_remove, ci->pool);
558
559   ci->app_ctx.bkt_alloc = serf_bucket_allocator_create(ci->pool, NULL, NULL);
560   ci->app_ctx.ssl_ctx = NULL;
561
562   ci->connection = serf_connection_create(ci->context, ci->address,
563                                           conn_setup, &ci->app_ctx,
564                                           closed_connection, &ci->app_ctx,
565                                           ci->pool);
566
567   ci->handler_ctx.method = apr_pstrdup(ci->pool, "GET");
568   ci->handler_ctx.host = apr_pstrdup(ci->pool, check->target);
569   ci->handler_ctx.path = ci->url.path;
570   ci->handler_ctx.authn = NULL;
571
572   ci->handler_ctx.acceptor = accept_response;
573   ci->handler_ctx.acceptor_baton = &ci->app_ctx;
574   ci->handler_ctx.handler = handle_response;
575   ci->handler_ctx.self = self;
576   ci->handler_ctx.check = check;
577
578   ci->request = serf_connection_request_create(ci->connection, setup_request,
579                                                &ci->handler_ctx);
580   serf_context_prerun(ci->context);
581
582   newe = eventer_alloc();
583   newe->mask = EVENTER_TIMER;
584   gettimeofday(&when, NULL);
585   p_int.tv_sec = check->timeout / 1000;
586   p_int.tv_usec = (check->timeout % 1000) * 1000;
587   add_timeval(when, p_int, &newe->whence);
588   ccl = calloc(1, sizeof(*ccl));
589   ccl->self = self;
590   ccl->check = check;
591   newe->closure = ccl;
592   newe->callback = serf_complete;
593   eventer_add(newe);
594   ci->timeout_event = newe;
595   return 0;
596 }
597 static int serf_schedule_next(noit_module_t *self,
598                               eventer_t e, noit_check_t check,
599                               struct timeval *now) {
600   eventer_t newe;
601   struct timeval last_check = { 0L, 0L };
602   struct timeval period, earliest;
603   serf_closure_t *ccl;
604
605   /* If we have an event, we know when we intended it to fire.  This means
606    * we should schedule that point + period.
607    */
608   if(now)
609     memcpy(&earliest, now, sizeof(earliest));
610   else
611     gettimeofday(&earliest, NULL);
612   if(e) memcpy(&last_check, &e->whence, sizeof(last_check));
613   period.tv_sec = check->period / 1000;
614   period.tv_usec = (check->period % 1000) * 1000;
615
616   newe = eventer_alloc();
617   memcpy(&newe->whence, &last_check, sizeof(last_check));
618   add_timeval(newe->whence, period, &newe->whence);
619   if(compare_timeval(newe->whence, earliest) < 0)
620     memcpy(&newe->whence, &earliest, sizeof(earliest));
621   newe->mask = EVENTER_TIMER;
622   newe->callback = serf_recur_handler;
623   ccl = calloc(1, sizeof(*ccl));
624   ccl->self = self;
625   ccl->check = check;
626   newe->closure = ccl;
627
628   eventer_add(newe);
629   check->fire_event = newe;
630   return 0;
631 }
632 static int serf_recur_handler(eventer_t e, int mask, void *closure,
633                               struct timeval *now) {
634   serf_closure_t *cl = (serf_closure_t *)closure;
635   serf_schedule_next(cl->self, e, cl->check, now);
636   serf_initiate(cl->self, cl->check);
637   free(cl);
638   return 0;
639 }
640 static int serf_initiate_check(noit_module_t *self, noit_check_t check,
641                                int once) {
642   if(!check->closure) check->closure = calloc(1, sizeof(serf_check_info_t));
643   if(once) {
644     serf_initiate(self, check);
645     return 0;
646   }
647   /* If check->fire_event, we're already scheduled... */
648   if(!check->fire_event)
649     serf_schedule_next(self, NULL, check, NULL);
650   return 0;
651 }
652 static int resmon_initiate_check(noit_module_t *self, noit_check_t check,
653                                  int once) {
654   /* resmon_check_info_t gives us a bit more space */
655   if(!check->closure) check->closure = calloc(1, sizeof(resmon_check_info_t));
656   if(once) {
657     serf_initiate(self, check);
658     return 0;
659   }
660   if(!check->fire_event)
661     serf_schedule_next(self, NULL, check, NULL);
662   return 0;
663 }
664
665
666 static int serf_onload(noit_module_t *self) {
667   apr_initialize();
668   atexit(apr_terminate);
669
670   nlerr = noit_log_stream_find("error/serf");
671   nldeb = noit_log_stream_find("debug/serf");
672   if(!nlerr) nlerr = noit_stderr;
673   if(!nldeb) nldeb = noit_debug;
674
675   eventer_name_callback("http/serf_handler", serf_handler);
676   eventer_name_callback("http/serf_complete", serf_complete);
677   eventer_name_callback("http/serf_recur_handler", serf_recur_handler);
678   return 0;
679 }
680 noit_module_t http = {
681   NOIT_MODULE_MAGIC,
682   NOIT_MODULE_ABI_VERSION,
683   "http",
684   "libserf-based HTTP and HTTPS resource checker",
685   serf_onload,
686   serf_config,
687   serf_init,
688   serf_initiate_check
689 };
690
691 noit_module_t resmon = {
692   NOIT_MODULE_MAGIC,
693   NOIT_MODULE_ABI_VERSION,
694   "resmon",
695   "libserf-based resmon resource checker",
696   serf_onload,
697   resmon_config,
698   serf_init,
699   resmon_initiate_check
700 };
701
Note: See TracBrowser for help on using the browser.