root/src/noit_poller.c

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

update logging to support faster avoidance, line numbers, filenames, etc.

  • 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 <assert.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13
14 #include "utils/noit_log.h"
15 #include "utils/noit_hash.h"
16 #include "noit_conf.h"
17 #include "noit_poller.h"
18 #include "noit_module.h"
19 #include "eventer/eventer.h"
20
21 static noit_hash_table polls = NOIT_HASH_EMPTY;
22 static u_int32_t __config_load_generation = 0;
23 struct uuid_dummy {
24   uuid_t foo;
25 };
26 #define UUID_SIZE sizeof(struct uuid_dummy)
27
28 static const char *
29 __noit_check_available_string(int16_t available) {
30   switch(available) {
31     case NP_AVAILABLE:    return "available";
32     case NP_UNAVAILABLE:  return "unavailable";
33     case NP_UNKNOWN:      return "unknown";
34   }
35   return "???";
36 }
37 static const char *
38 __noit_check_state_string(int16_t state) {
39   switch(state) {
40     case NP_GOOD:         return "good";
41     case NP_BAD:          return "bad";
42     case NP_UNKNOWN:      return "unknown";
43   }
44   return "???";
45 }
46 void
47 noit_poller_load_checks() {
48   int i, cnt = 0;
49   noit_conf_section_t *sec;
50   __config_load_generation++;
51   sec = noit_conf_get_sections(NULL, "/noit/checks//check", &cnt);
52   for(i=0; i<cnt; i++) {
53     char uuid_str[37];
54     char target[256];
55     char module[256];
56     char name[256];
57     int period, timeout;
58     uuid_t uuid, out_uuid;
59     noit_hash_table *options;
60
61     if(!noit_conf_get_stringbuf(sec[i], "@uuid",
62                                 uuid_str, sizeof(uuid_str))) {
63       noitL(noit_stderr, "check %d has no uuid\n", i+1);
64       continue;
65     }
66     if(uuid_parse(uuid_str, uuid)) {
67       noitL(noit_stderr, "check uuid: '%s' is invalid\n", uuid_str);
68       continue;
69     }
70     if(!noit_conf_get_stringbuf(sec[i], "target", target, sizeof(target))) {
71       if(!noit_conf_get_stringbuf(sec[i], "../target", target, sizeof(target))) {
72          noitL(noit_stderr, "check uuid: '%s' has no target\n",
73                   uuid_str);
74          continue;
75       }
76     }
77     if(!noit_conf_get_stringbuf(sec[i], "module", module, sizeof(module))) {
78       if(!noit_conf_get_stringbuf(sec[i], "../module", module, sizeof(module))) {
79         noitL(noit_stderr, "check uuid: '%s' has no module\n",
80                  uuid_str);
81         continue;
82       }
83     }
84     if(!noit_conf_get_stringbuf(sec[i], "name", name, sizeof(name))) {
85       strcpy(name, module);
86     }
87     if(!noit_conf_get_int(sec[i], "period", &period)) {
88       if(!noit_conf_get_int(sec[i], "../period", &period)) {
89         noitL(noit_stderr, "check uuid: '%s' has no period\n", uuid_str);
90         continue;
91       }
92     }
93     if(!noit_conf_get_int(sec[i], "timeout", &timeout)) {
94       if(!noit_conf_get_int(sec[i], "../timeout", &timeout)) {
95         noitL(noit_stderr, "check uuid: '%s' has no timeout\n", uuid_str);
96         continue;
97       }
98     }
99     if(timeout >= period) {
100       noitL(noit_stderr, "check uuid: '%s' timeout > period\n", uuid_str);
101       timeout = period/2;
102     }
103     options = noit_conf_get_hash(sec[i], "config/*");
104     noit_poller_schedule(target, module, name, options,
105                          period, timeout, uuid, out_uuid);
106     noitL(noit_debug, "loaded uuid: %s\n", uuid_str);
107   }
108 }
109
110 void
111 noit_poller_initiate() {
112   noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
113   uuid_t key_id;
114   int klen;
115   noit_check_t check;
116   while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen,
117                        (void **)&check)) {
118     noit_module_t *mod;
119     mod = noit_module_lookup(check->module);
120     if(mod) {
121       mod->initiate_check(mod, check);
122     }
123     else {
124       noitL(noit_stderr, "Cannot find module '%s'\n", check->module);
125     }
126   }
127 }
128
129 void
130 noit_poller_init() {
131   noit_poller_load_checks();
132   noit_poller_initiate();
133 }
134
135 int
136 noit_poller_schedule(const char *target,
137                      const char *module,
138                      const char *name,
139                      noit_hash_table *config,
140                      u_int32_t period,
141                      u_int32_t timeout,
142                      uuid_t in,
143                      uuid_t out) {
144   int8_t family;
145   int rv;
146   union {
147     struct in_addr addr4;
148     struct in6_addr addr6;
149   } a;
150   noit_check_t new_check;
151
152
153   family = AF_INET;
154   rv = inet_pton(family, target, &a);
155   if(rv != 1) {
156     family = AF_INET6;
157     rv = inet_pton(family, target, &a);
158     if(rv != 1) {
159       noitL(noit_stderr, "Cannot translate '%s' to IP\n", target);
160       return -1;
161     }
162   }
163
164   new_check = calloc(1, sizeof(*new_check));
165   if(!new_check) return -1;
166   new_check->generation = __config_load_generation;
167   new_check->target_family = family;
168   memcpy(&new_check->target_addr, &a, sizeof(a));
169   new_check->target = strdup(target);
170   new_check->module = strdup(module);
171   new_check->name = name?strdup(name):NULL;
172
173   if(config != NULL) {
174     noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
175     const char *k;
176     int klen;
177     void *data;
178     new_check->config = calloc(1, sizeof(*new_check->config));
179     while(noit_hash_next(config, &iter, &k, &klen, &data)) {
180       noit_hash_store(new_check->config, strdup(k), klen, strdup((char *)data));
181     }
182   }
183   new_check->period = period;
184   new_check->timeout = timeout;
185   new_check->flags = 0;
186   if(uuid_is_null(in))
187     uuid_generate(new_check->checkid);
188   else
189     uuid_copy(new_check->checkid, in);
190
191   assert(noit_hash_store(&polls,
192                          (char *)new_check->checkid, UUID_SIZE,
193                          new_check));
194   uuid_copy(out, new_check->checkid);
195   return 0;
196 }
197
198 int
199 noit_poller_deschedule(uuid_t in) {
200   noit_check_t checker;
201   if(noit_hash_retrieve(&polls,
202                         (char *)in, UUID_SIZE,
203                         (void **)&checker) == 0) {
204     return -1;
205   }
206   if(checker->flags & NP_RUNNING) {
207     checker->flags |= NP_KILLED;
208     return 0;
209   }
210   if(checker->fire_event) {
211      eventer_remove(checker->fire_event);
212      eventer_free(checker->fire_event);
213      checker->fire_event = NULL;
214   }
215   noit_hash_delete(&polls, (char *)in, UUID_SIZE, free, free);
216
217   if(checker->target) free(checker->target);
218   if(checker->module) free(checker->module);
219   if(checker->name) free(checker->name);
220   if(checker->config) {
221     noit_hash_destroy(checker->config, free, free);
222     free(checker->config);
223     checker->config = NULL;
224   }
225   free(checker);
226   return 0;
227 }
228
229 noit_check_t
230 noit_poller_lookup(uuid_t in) {
231   noit_check_t check;
232   if(noit_hash_retrieve(&polls,
233                         (char *)in, UUID_SIZE,
234                         (void **)&check)) {
235     return check;
236   }
237   return NULL;
238 }
239
240
241 void
242 noit_poller_set_state(noit_check_t check, stats_t *newstate) {
243   int report_change = 0;
244   if(check->stats.previous.status)
245     free(check->stats.previous.status);
246   memcpy(&check->stats.previous, &check->stats.current, sizeof(stats_t));
247   memcpy(&check->stats.current, newstate, sizeof(stats_t));
248   if(check->stats.current.status)
249     check->stats.current.status = strdup(check->stats.current.status);
250
251   /* check for state changes */
252   if(check->stats.current.available != 0 &&
253      check->stats.previous.available != 0 &&
254      check->stats.current.available != check->stats.previous.available)
255     report_change = 1;
256   if(check->stats.current.state != 0 &&
257      check->stats.previous.state != 0 &&
258      check->stats.current.state != check->stats.previous.state)
259     report_change = 1;
260
261   if(report_change) {
262     noitL(noit_debug, "%s/%s -> [%s/%s]\n",
263           check->target, check->module,
264           __noit_check_available_string(check->stats.current.available),
265           __noit_check_state_string(check->stats.current.state));
266   }
267 }
Note: See TracBrowser for help on using the browser.