static int check_test_sweeper(eventer_t e, int mask, void *closure, struct timeval *now) { int left = 0; noit_skiplist_node *iter = NULL; sweeper_event = NULL; iter = noit_skiplist_getlist(&in_progress); while(iter) { struct check_test_closure *cl = iter->data; /* advance here, we might delete */ noit_skiplist_next(&in_progress,&iter); if(NOIT_CHECK_DISABLED(cl->check)) { if(NOIT_CHECK_SHOULD_RESOLVE(cl->check)) noit_check_resolve(cl->check); if(NOIT_CHECK_RESOLVED(cl->check)) { noit_module_t *m = noit_module_lookup(cl->check->module); cl->check->flags &= ~NP_DISABLED; if(NOIT_CHECK_SHOULD_RESOLVE(cl->check)) noitL(nldeb, "translated to %s\n", cl->check->target_ip); if(m) m->initiate_check(m, cl->check, 1, NULL); } left++; } else if(NOIT_CHECK_RUNNING(cl->check)) left++; else noit_skiplist_remove(&in_progress, cl->restc, (noit_freefunc_t)rest_test_check_result); } if(left) check_test_schedule_sweeper(); return 0; }
int noit_check_schedule_next(noit_module_t *self, struct timeval *last_check, noit_check_t *check, struct timeval *now, dispatch_func_t dispatch, noit_check_t *cause) { eventer_t newe; struct timeval period, earliest; recur_closure_t *rcl; assert(cause == NULL); assert(check->fire_event == NULL); if(check->period == 0) return 0; if(NOIT_CHECK_DISABLED(check) || NOIT_CHECK_KILLED(check)) { if(!(check->flags & NP_TRANSIENT)) check_slots_dec_tv(last_check); return 0; } /* If we have an event, we know when we intended it to fire. This means * we should schedule that point + period. */ if(now) memcpy(&earliest, now, sizeof(earliest)); else gettimeofday(&earliest, NULL); /* If the check is unconfigured and needs resolving, we'll set the * period down a bit lower so we can pick up the resolution quickly. */ if(!NOIT_CHECK_RESOLVED(check) && NOIT_CHECK_SHOULD_RESOLVE(check) && check->period > 1000) { period.tv_sec = 1; period.tv_usec = 0; } else { period.tv_sec = check->period / 1000; period.tv_usec = (check->period % 1000) * 1000; } newe = eventer_alloc(); memcpy(&newe->whence, last_check, sizeof(*last_check)); add_timeval(newe->whence, period, &newe->whence); if(compare_timeval(newe->whence, earliest) < 0) memcpy(&newe->whence, &earliest, sizeof(earliest)); newe->mask = EVENTER_TIMER; newe->callback = noit_check_recur_handler; rcl = calloc(1, sizeof(*rcl)); rcl->self = self; rcl->check = check; rcl->cause = cause; rcl->dispatch = dispatch; newe->closure = rcl; eventer_add(newe); check->fire_event = newe; return 0; }
noit_check_t * noit_fire_check(xmlNodePtr attr, xmlNodePtr config, const char **error) { char *target = NULL, *name = NULL, *module = NULL, *filterset = NULL; int timeout = 0; noit_module_t *m; noit_check_t *c = NULL; xmlNodePtr a, co; noit_hash_table *conf_hash = NULL; for(a = attr->children; a; a = a->next) { if(!strcmp((char *)a->name, "target")) target = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "name")) name = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "module")) module = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "filterset")) filterset = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "timeout")) { char *timeout_str = (char *)xmlNodeGetContent(a); timeout = atoi(timeout_str); free(timeout_str); } } m = noit_module_lookup(module); if(!m) { *error = "cannot find requested module"; goto error; } conf_hash = calloc(1, sizeof(*conf_hash)); for(co = config->children; co; co = co->next) { char *name, *val; xmlChar *tmp_val; name = strdup((char *)co->name); tmp_val = xmlNodeGetContent(co); val = strdup(tmp_val ? (char *)tmp_val : ""); noit_hash_replace(conf_hash, name, strlen(name), val, free, free); xmlFree(tmp_val); } if(!m->initiate_check) { *error = "that module cannot run checks"; goto error; } c = calloc(1, sizeof(*c)); noit_check_update(c, target, name, filterset, conf_hash, 0, timeout, NULL, NP_TRANSIENT); c->module = strdup(module); uuid_generate(c->checkid); c->flags |= NP_DISABLED; /* this is hack to know we haven't run it yet */ if(NOIT_CHECK_SHOULD_RESOLVE(c)) noit_check_resolve(c); error: if(conf_hash) { noit_hash_destroy(conf_hash, free, free); free(conf_hash); } if(target) xmlFree(target); if(name) xmlFree(name); if(module) xmlFree(module); if(filterset) xmlFree(filterset); return c; }
noit_check_t * noit_fire_check(xmlNodePtr attr, xmlNodePtr config, const char **error) { char *target = NULL, *name = NULL, *module = NULL, *filterset = NULL; char *resolve_rtype = NULL; int timeout = 0, flags = NP_TRANSIENT, i, mod_cnt; noit_module_t *m; noit_check_t *c = NULL; xmlNodePtr a, co; noit_hash_table *conf_hash = NULL; noit_hash_table **moptions = NULL; for(a = attr->children; a; a = a->next) { if(!strcmp((char *)a->name, "target")) target = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "name")) name = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "module")) module = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "filterset")) filterset = (char *)xmlNodeGetContent(a); else if(!strcmp((char *)a->name, "timeout")) { char *timeout_str = (char *)xmlNodeGetContent(a); timeout = atoi(timeout_str); free(timeout_str); } else if(!strcmp((char *)a->name, "resolve_rtype")) resolve_rtype = (char *)xmlNodeGetContent(a); } m = noit_module_lookup(module); if(!m) { *error = "cannot find requested module"; goto error; } conf_hash = calloc(1, sizeof(*conf_hash)); if(config) { for(co = config->children; co; co = co->next) { char *name, *val; xmlChar *tmp_val; name = strdup((char *)co->name); tmp_val = xmlNodeGetContent(co); val = strdup(tmp_val ? (char *)tmp_val : ""); noit_hash_replace(conf_hash, name, strlen(name), val, free, free); xmlFree(tmp_val); } } mod_cnt = noit_check_registered_module_cnt(); if(mod_cnt > 0) { moptions = alloca(mod_cnt * sizeof(*moptions)); memset(moptions, 0, mod_cnt * sizeof(*moptions)); for(i=0; i<mod_cnt; i++) { const char *name; noit_conf_section_t checks; name = noit_check_registered_module(i); checks = noit_conf_get_section(NULL, "/noit/checks"); if(name) moptions[i] = noit_conf_get_namespaced_hash(checks, "config", name); } } if(!m->initiate_check) { *error = "that module cannot run checks"; goto error; } flags |= noit_calc_rtype_flag(resolve_rtype); c = calloc(1, sizeof(*c)); noit_check_update(c, target, name, filterset, conf_hash, moptions, 0, timeout, NULL, flags); c->module = strdup(module); uuid_generate(c->checkid); c->flags |= NP_DISABLED; /* this is hack to know we haven't run it yet */ if(NOIT_CHECK_SHOULD_RESOLVE(c)) noit_check_resolve(c); error: if(conf_hash) { noit_hash_destroy(conf_hash, free, free); free(conf_hash); } if(moptions) { for(i=0; i<mod_cnt; i++) { if(moptions[i]) { noit_hash_destroy(moptions[i], free, free); free(moptions[i]); } } } if(target) xmlFree(target); if(name) xmlFree(name); if(module) xmlFree(module); if(filterset) xmlFree(filterset); if (resolve_rtype) xmlFree(resolve_rtype); return c; }
int noit_check_schedule_next(noit_module_t *self, struct timeval *last_check, noit_check_t *check, struct timeval *now, dispatch_func_t dispatch, noit_check_t *cause) { eventer_t newe; struct timeval period, earliest, diff; int64_t diffms, periodms, offsetms; recur_closure_t *rcl; int initial = last_check ? 1 : 0; assert(cause == NULL); assert(check->fire_event == NULL); if(check->period == 0) return 0; /* if last_check is not passed, we use the initial_schedule_time * otherwise, we set the initial_schedule_time */ if(!last_check) last_check = &check->initial_schedule_time; else memcpy(&check->initial_schedule_time, last_check, sizeof(*last_check)); if(NOIT_CHECK_DISABLED(check) || NOIT_CHECK_KILLED(check)) { if(!(check->flags & NP_TRANSIENT)) check_slots_dec_tv(last_check); memset(&check->initial_schedule_time, 0, sizeof(struct timeval)); return 0; } /* If we have an event, we know when we intended it to fire. This means * we should schedule that point + period. */ if(now) memcpy(&earliest, now, sizeof(earliest)); else gettimeofday(&earliest, NULL); /* If the check is unconfigured and needs resolving, we'll set the * period down a bit lower so we can pick up the resolution quickly. * The one exception is if this is the initial run. */ if(!initial && !NOIT_CHECK_RESOLVED(check) && NOIT_CHECK_SHOULD_RESOLVE(check) && check->period > 1000) { period.tv_sec = 1; period.tv_usec = 0; } else { period.tv_sec = check->period / 1000; period.tv_usec = (check->period % 1000) * 1000; } periodms = period.tv_sec * 1000 + period.tv_usec / 1000; newe = eventer_alloc(); /* calculate the differnet between the initial schedule time and "now" */ if(compare_timeval(earliest, *last_check) >= 0) { sub_timeval(earliest, *last_check, &diff); diffms = (int64_t)diff.tv_sec * 1000 + diff.tv_usec / 1000; } else { noitL(noit_error, "time is going backwards. abort.\n"); abort(); } /* determine the offset from initial schedule time that would place * us at the next period-aligned point past "now" */ offsetms = ((diffms / periodms) + 1) * periodms; diff.tv_sec = offsetms / 1000; diff.tv_usec = (offsetms % 1000) * 1000; memcpy(&newe->whence, last_check, sizeof(*last_check)); add_timeval(newe->whence, diff, &newe->whence); sub_timeval(newe->whence, earliest, &diff); diffms = (int64_t)diff.tv_sec * 1000 + (int)diff.tv_usec / 1000; assert(compare_timeval(newe->whence, earliest) > 0); newe->mask = EVENTER_TIMER; newe->callback = noit_check_recur_handler; rcl = calloc(1, sizeof(*rcl)); rcl->self = self; rcl->check = check; rcl->cause = cause; rcl->dispatch = dispatch; newe->closure = rcl; eventer_add(newe); check->fire_event = newe; return diffms; }