void noit_poller_make_causal_map() { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; uuid_t key_id; int klen; void *vcheck; /* Cleanup any previous causal map */ while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen, &vcheck)) { noit_check_t *check = (noit_check_t *)vcheck; dep_list_t *dep; while((dep = check->causal_checks) != NULL) { check->causal_checks = dep->next; free(dep); } } memset(&iter, 0, sizeof(iter)); /* Walk all checks and add check dependencies to their parents */ while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen, &vcheck)) { noit_check_t *check = (noit_check_t *)vcheck, *parent; if(check->oncheck) { /* This service is causally triggered by another service */ char fullcheck[1024]; char *name = check->oncheck; char *target = NULL; noitL(noit_debug, "Searching for upstream trigger on %s\n", name); if((target = strchr(check->oncheck, '`')) != NULL) { strlcpy(fullcheck, check->oncheck, target - check->oncheck); name = target + 1; target = fullcheck; } else target = check->target; parent = noit_poller_lookup_by_name(target, name); if(!parent) { check->flags |= NP_DISABLED; noitL(noit_stderr, "Disabling check %s`%s, can't find oncheck %s`%s\n", check->target, check->name, target, name); } else { dep_list_t *dep; dep = malloc(sizeof(*dep)); dep->check = check; dep->next = parent->causal_checks; parent->causal_checks = dep; noitL(noit_debug, "Causal map %s`%s --> %s`%s\n", parent->target, parent->name, check->target, check->name); } } } }
void noit_poller_flush_epoch(int oldest_allowed) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; uuid_t key_id; int klen; noit_check_t *tofree = NULL; void *vcheck; /* Cleanup any previous causal map */ while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen, &vcheck)) { noit_check_t *check = (noit_check_t *)vcheck; /* We don't free the one we're looking at... we free it on the next * pass. This leaves out iterator in good shape. We just need to * remember to free it one last time outside the while loop, down... */ if(tofree) { noit_poller_deschedule(tofree->checkid); tofree = NULL; } if(check->generation < oldest_allowed) { tofree = check; } } /* ... here */ if(tofree) noit_poller_deschedule(tofree->checkid); }
xmlNodePtr noit_check_state_as_xml(noit_check_t *check) { xmlNodePtr state, tmp, metrics; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; stats_t *c = &check->stats.current; state = xmlNewNode(NULL, (xmlChar *)"state"); NODE_CONTENT(state, "running", NOIT_CHECK_RUNNING(check)?"true":"false"); NODE_CONTENT(state, "killed", NOIT_CHECK_KILLED(check)?"true":"false"); NODE_CONTENT(state, "configured", NOIT_CHECK_CONFIGURED(check)?"true":"false"); NODE_CONTENT(state, "disabled", NOIT_CHECK_DISABLED(check)?"true":"false"); NODE_CONTENT(state, "target_ip", check->target_ip); xmlAddChild(state, (tmp = xmlNewNode(NULL, (xmlChar *)"last_run"))); if(check->stats.current.whence.tv_sec) { struct timeval f = check->stats.current.whence; struct timeval n; char timestr[20]; gettimeofday(&n, NULL); snprintf(timestr, sizeof(timestr), "%0.3f", n.tv_sec + (n.tv_usec / 1000000.0)); xmlSetProp(tmp, (xmlChar *)"now", (xmlChar *)timestr); snprintf(timestr, sizeof(timestr), "%0.3f", f.tv_sec + (f.tv_usec / 1000000.0)); xmlNodeAddContent(tmp, (xmlChar *)timestr); } if(c->available) { /* truth here means the check has been run */ char buff[20], *compiler_warning; snprintf(buff, sizeof(buff), "%0.3f", (float)c->duration/1000.0); compiler_warning = buff; NODE_CONTENT(state, "runtime", compiler_warning); } NODE_CONTENT(state, "availability", noit_check_available_string(c->available)); NODE_CONTENT(state, "state", noit_check_state_string(c->state)); NODE_CONTENT(state, "status", c->status ? c->status : ""); memset(&iter, 0, sizeof(iter)); xmlAddChild(state, (metrics = xmlNewNode(NULL, (xmlChar *)"metrics"))); while(noit_hash_next(&c->metrics, &iter, &k, &klen, &data)) { char buff[256]; metric_t *m = (metric_t *)data; xmlAddChild(metrics, (tmp = xmlNewNode(NULL, (xmlChar *)"metric"))); xmlSetProp(tmp, (xmlChar *)"name", (xmlChar *)m->metric_name); buff[0] = m->metric_type; buff[1] = '\0'; xmlSetProp(tmp, (xmlChar *)"type", (xmlChar *)buff); if(m->metric_value.s) { int rv; rv = noit_stats_snprint_metric_value(buff, sizeof(buff), m); if(rv < 0) xmlSetProp(tmp, (xmlChar *)"error", (xmlChar *)"unknown type"); else xmlNodeAddContent(tmp, (xmlChar *)buff); } } return state; }
char * noit_console_check_opts(noit_console_closure_t ncct, noit_console_state_stack_t *stack, noit_console_state_t *dstate, int argc, char **argv, int idx) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; uuid_t key_id; int klen, i = 0; if(argc == 1) { void *vcheck; while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen, &vcheck)) { char out[512]; char uuid_str[37]; noit_check_t *check = (noit_check_t *)vcheck; snprintf(out, sizeof(out), "%s`%s", check->target, check->name); uuid_unparse_lower(check->checkid, uuid_str); if(!strncmp(out, argv[0], strlen(argv[0]))) { if(idx == i) return strdup(out); i++; } if(!strncmp(uuid_str, argv[0], strlen(argv[0]))) { if(idx == i) return strdup(uuid_str); i++; } } } if(argc == 2) { return noit_console_opt_delegate(ncct, stack, dstate, argc-1, argv+1, idx); } return NULL; }
static int stratcon_datastore_journal_sync(eventer_t e, int mask, void *closure, struct timeval *now) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *vij; interim_journal_t *ij; syncset_t *syncset = closure; if((mask & EVENTER_ASYNCH) == EVENTER_ASYNCH) { if(syncset->completion) { eventer_add(syncset->completion); eventer_trigger(syncset->completion, EVENTER_READ | EVENTER_WRITE); } free(syncset); return 0; } if(!((mask & EVENTER_ASYNCH_WORK) == EVENTER_ASYNCH_WORK)) return 0; noitL(ds_deb, "Syncing journal sets...\n"); if (syncset->ws) { while(noit_hash_next(syncset->ws, &iter, &k, &klen, &vij)) { char tmppath[PATH_MAX], id_str[32]; int suffix_idx; ij = vij; noitL(ds_deb, "Syncing journal set [%s,%s,%s]\n", ij->remote_str, ij->remote_cn, ij->fqdn); strlcpy(tmppath, ij->filename, sizeof(tmppath)); suffix_idx = strlen(ij->filename) - 4; /* . t m p */ ij->filename[suffix_idx] = '\0'; if(rename(tmppath, ij->filename) != 0) { if(errno == EEXIST) { unlink(ij->filename); if(rename(tmppath, ij->filename) != 0) goto rename_failed; } else { rename_failed: noitL(noit_error, "rename failed(%s): (%s->%s)\n", strerror(errno), tmppath, ij->filename); exit(-1); } } fsync(ij->fd); close(ij->fd); ij->fd = -1; snprintf(id_str, sizeof(id_str), "%d", ij->storagenode_id); stratcon_ingest(ij->filename, ij->remote_str, ij->remote_cn, id_str); } noit_hash_destroy(syncset->ws, free, interim_journal_free); free(syncset->ws); } else { noitL(noit_error, "attempted to sync non-existing working set\n"); } return 0; }
void noit_poller_initiate() { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; uuid_t key_id; int klen; void *vcheck; while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen, &vcheck)) { noit_check_activate((noit_check_t *)vcheck); } }
int noit_jlog_foreach_feed_stats(int (*f)(jlog_feed_stats_t *, void *), void *c) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *key; int klen, cnt = 0; void *vs; while(noit_hash_next(&feed_stats, &iter, &key, &klen, &vs)) { cnt += f((jlog_feed_stats_t *)vs, c); } return cnt; }
int noit_log_list(noit_log_stream_t *loggers, int nsize) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen, count = 0, total = 0, out_of_space_flag = 1; void *data; while(noit_hash_next(&noit_loggers, &iter, &k, &klen, &data)) { if(count < nsize) loggers[count++] = (noit_log_stream_t)data; else out_of_space_flag = -1; total++; } return total * out_of_space_flag; }
int noit_log_reopen_all() { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen, rv = 0; void *data; noit_log_stream_t ls; while(noit_hash_next(&noit_loggers, &iter, &k, &klen, &data)) { ls = data; if(ls->ops) if(ls->ops->reopenop(ls) < 0) rv = -1; } return rv; }
static void noit_log_dematerialize() { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; while(noit_hash_next(&noit_loggers, &iter, &k, &klen, &data)) { noit_log_stream_t ls = data; ls->deps_materialized = 0; ls->flags &= ~NOIT_LOG_STREAM_RECALCULATE; debug_printf("dematerializing(%s)\n", ls->name); } }
static int noit_console_show_checks(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *dstate, void *closure) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; uuid_t key_id; int klen; void *vcheck; while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen, &vcheck)) { nc_printf_check_brief(ncct, (noit_check_t *)vcheck); } return 0; }
static noit_hook_return_t ip_acl_hook_impl(void *closure, noit_module_t *self, noit_check_t *check, noit_check_t *cause) { char deny_msg[128]; stats_t current; noit_hash_table *config; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k = NULL; int klen; void *data; config = noit_check_get_module_config(check, ip_acl_module_id); if(!config || config->size == 0) return NOIT_HOOK_CONTINUE; while(noit_hash_next(config, &iter, &k, &klen, &data)) { if(k) { void *dir = NULL; unsigned char mask; if(noit_hash_retrieve(&acls, k, strlen(k), &data)) { btrie *acl = data; if(check->target_family == AF_INET) { dir = noit_find_bpm_route_ipv4(acl, &check->target_addr.addr, &mask); if(dir == DENY_PTR) goto prevent; else if(dir == ALLOW_PTR) return NOIT_HOOK_CONTINUE; } else if(check->target_family == AF_INET6) { dir = noit_find_bpm_route_ipv6(acl, &check->target_addr.addr6, &mask); if(dir == DENY_PTR) goto prevent; else if(dir == ALLOW_PTR) return NOIT_HOOK_CONTINUE; } } } } return NOIT_HOOK_CONTINUE; prevent: memset(¤t, 0, sizeof(current)); current.available = NP_UNAVAILABLE; current.state = NP_BAD; gettimeofday(¤t.whence, NULL); snprintf(deny_msg, sizeof(deny_msg), "prevented by ACL '%s'", k ? k : "unknown"); current.status = deny_msg; noit_check_set_stats(check, ¤t); return NOIT_HOOK_DONE; }
static int noit_console_show_dns(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *dstate, void *closure) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; uuid_t key_id; int klen; void *vts; pthread_mutex_lock(&dns_ctx_store_lock); while(noit_hash_next(&dns_ctx_store, &iter, (const char **)key_id, &klen, &vts)) { dns_ctx_handle_t *h = vts; nc_printf_dns_handle_brief(ncct, h); } pthread_mutex_unlock(&dns_ctx_store_lock); return 0; }
char * noit_console_conf_check_opts(noit_console_closure_t ncct, noit_console_state_stack_t *stack, noit_console_state_t *dstate, int argc, char **argv, int idx) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; uuid_t key_id; int klen, i = 0; void *vcheck; if(argc == 1) { if(!strncmp("new", argv[0], strlen(argv[0]))) { if(idx == i) return strdup("new"); i++; } while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen, &vcheck)) { noit_check_t *check = (noit_check_t *)vcheck; char out[512]; char uuid_str[37]; snprintf(out, sizeof(out), "%s`%s", check->target, check->name); uuid_unparse_lower(check->checkid, uuid_str); if(!strncmp(out, argv[0], strlen(argv[0]))) { if(idx == i) return strdup(out); i++; } if(!strncmp(uuid_str, argv[0], strlen(argv[0]))) { if(idx == i) return strdup(uuid_str); i++; } } } if(argc == 2) { cmd_info_t *cmd; if(!strcmp("new", argv[0])) return NULL; cmd = noit_skiplist_find(&dstate->cmds, "attribute", NULL); if(!cmd) return NULL; return noit_console_opt_delegate(ncct, stack, cmd->dstate, argc-1, argv+1, idx); } return NULL; }
static int noit_console_config_show(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *state, void *closure) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; int i, cnt, titled = 0, cliplen = 0; const char *path = "", *basepath = NULL; char xpath[1024]; noit_conf_t_userdata_t *info = NULL; noit_hash_table *config; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL, current_ctxt; xmlDocPtr master_config = NULL; xmlNodePtr node = NULL; noit_conf_xml_xpath(&master_config, &xpath_ctxt); if(argc > 1) { nc_printf(ncct, "too many arguments\n"); return -1; } info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); if(info && info->path) path = basepath = info->path; if(!info && argc == 0) { nc_printf(ncct, "argument required when not in configuration mode\n"); return -1; } if(argc == 1) path = argv[0]; if(!basepath) basepath = path; /* { / } is a special case */ if(!strcmp(basepath, "/")) basepath = ""; if(!strcmp(path, "/")) path = ""; if(!master_config) { nc_printf(ncct, "no config\n"); return -1; } /* { / } is the only path that will end with a / * in XPath { / / * } means something _entirely different than { / * } * Ever notice how it is hard to describe xpath in C comments? */ /* We don't want to show the root node */ cliplen = strlen("/noit/"); /* If we are in configuration mode * and we are without an argument or the argument is absolute, * clip the current path off */ if(info && (argc == 0 || path[0] != '/')) cliplen += strlen(basepath); if(!path[0] || path[0] == '/') /* base only, or absolute path requested */ snprintf(xpath, sizeof(xpath), "/noit%s/@*", path); else snprintf(xpath, sizeof(xpath), "/noit%s/%s/@*", basepath, path); current_ctxt = xpath_ctxt; pobj = xmlXPathEval((xmlChar *)xpath, current_ctxt); if(!pobj || pobj->type != XPATH_NODESET) { nc_printf(ncct, "no such object\n"); goto bad; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); titled = 0; for(i=0; i<cnt; i++) { node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); if(!strcmp((char *)node->name, "check")) continue; if(node->children && node->children == xmlGetLastChild(node) && xmlNodeIsText(node->children)) { if(!titled++) nc_printf(ncct, "== Section Settings ==\n"); nc_printf(ncct, "%s: %s\n", xmlGetNodePath(node) + cliplen, xmlXPathCastNodeToString(node->children)); } } xmlXPathFreeObject(pobj); /* Print out all the config settings */ if(!path[0] || path[0] == '/') /* base only, or absolute path requested */ snprintf(xpath, sizeof(xpath), "/noit%s", path); else snprintf(xpath, sizeof(xpath), "/noit%s/%s", basepath, path); pobj = xmlXPathEval((xmlChar *)xpath, current_ctxt); if(!pobj || pobj->type != XPATH_NODESET) { nc_printf(ncct, "no such object\n"); goto bad; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); if(cnt > 0) { node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); titled = 0; config = noit_conf_get_hash(node, "config"); while(noit_hash_next(config, &iter, &k, &klen, &data)) { if(!titled++) nc_printf(ncct, "== Section [Aggregated] Config ==\n"); nc_printf(ncct, "config::%s: %s\n", k, (const char *)data); } noit_hash_destroy(config, free, free); free(config); } xmlXPathFreeObject(pobj); /* _shorten string_ turning last { / @ * } to { / * } */ if(!path[0] || path[0] == '/') /* base only, or absolute path requested */ snprintf(xpath, sizeof(xpath), "/noit%s/*", path); else snprintf(xpath, sizeof(xpath), "/noit%s/%s/*", basepath, path); pobj = xmlXPathEval((xmlChar *)xpath, current_ctxt); if(!pobj || pobj->type != XPATH_NODESET) { nc_printf(ncct, "no such object\n"); goto bad; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); titled = 0; for(i=0; i<cnt; i++) { node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); if(!strcmp((char *)node->name, "check")) continue; if(!strcmp((char *)node->name, "filterset")) continue; if(!strcmp((char *)xmlGetNodePath(node) + cliplen, "config")) continue; if(!(node->children && node->children == xmlGetLastChild(node) && xmlNodeIsText(node->children))) { if(!titled++) nc_printf(ncct, "== Subsections ==\n"); nc_printf(ncct, "%s\n", xmlGetNodePath(node) + cliplen); } } titled = 0; for(i=0; i<cnt; i++) { node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); if(!strcmp((char *)node->name, "filterset")) { xmlAttr *attr; char *filter_name = NULL; for(attr=node->properties; attr; attr = attr->next) { if(!strcmp((char *)attr->name, "name")) filter_name = (char *)xmlXPathCastNodeToString(attr->children); } if(filter_name) { nc_printf(ncct, "filterset[@name=\"%s\"]\n", filter_name); xmlFree(filter_name); } else nc_printf(ncct, "fitlerset\n"); } else if(!strcmp((char *)node->name, "check")) { int busted = 1; xmlAttr *attr; char *uuid_str = "undefined"; if(!titled++) nc_printf(ncct, "== Checks ==\n"); for(attr=node->properties; attr; attr = attr->next) { if(!strcmp((char *)attr->name, "uuid")) uuid_str = (char *)xmlXPathCastNodeToString(attr->children); } if(uuid_str) { uuid_t checkid; nc_printf(ncct, "check[@uuid=\"%s\"] ", uuid_str); if(uuid_parse(uuid_str, checkid) == 0) { noit_check_t *check; check = noit_poller_lookup(checkid); if(check) { busted = 0; nc_printf(ncct, "%s`%s`%s", check->target, check->module, check->name); } } } else nc_printf(ncct, "%s ", xmlGetNodePath(node) + cliplen); if(busted) nc_printf(ncct, "[check not in running system]"); nc_write(ncct, "\n", 1); } } xmlXPathFreeObject(pobj); return 0; bad: if(pobj) xmlXPathFreeObject(pobj); return -1; }
static int noit_console_show_check(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *state, void *closure) { int i, cnt; noit_conf_t_userdata_t *info; char xpath[1024]; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; noit_conf_xml_xpath(NULL, &xpath_ctxt); if(argc > 1) { nc_printf(ncct, "requires zero or one arguments\n"); return -1; } info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); /* We many not be in conf-t mode -- that's fine */ if(noit_console_mkcheck_xpath(xpath, sizeof(xpath), info, argc ? argv[0] : NULL)) { nc_printf(ncct, "could not find check '%s'\n", argv[0]); return -1; } pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET || xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { nc_printf(ncct, "no checks found\n"); goto out; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); if(info && cnt != 1) { nc_printf(ncct, "Ambiguous check specified\n"); goto out; } for(i=0; i<cnt; i++) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; uuid_t checkid; noit_check_t *check; noit_hash_table *config; xmlNodePtr node, anode, mnode = NULL; char *uuid_conf; char *module, *value; node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid"); if(!uuid_conf || uuid_parse(uuid_conf, checkid)) { nc_printf(ncct, "%s has invalid or missing UUID!\n", (char *)xmlGetNodePath(node) + strlen("/noit")); continue; } nc_printf(ncct, "==== %s ====\n", uuid_conf); #define MYATTR(a,n,b) _noit_conf_get_string(node, &(n), "@" #a, &(b)) #define INHERIT(a,n,b) \ _noit_conf_get_string(node, &(n), "ancestor-or-self::node()/@" #a, &(b)) #define SHOW_ATTR(a) do { \ anode = NULL; \ value = NULL; \ INHERIT(a, anode, value); \ nc_attr_show(ncct, #a, node, anode, value); \ } while(0) if(!INHERIT(module, mnode, module)) module = NULL; if(MYATTR(name, anode, value)) nc_printf(ncct, " name: %s\n", value); else nc_printf(ncct, " name: %s [from module]\n", module ? module : "[undef]"); nc_attr_show(ncct, "module", node, mnode, module); SHOW_ATTR(target); SHOW_ATTR(period); SHOW_ATTR(timeout); SHOW_ATTR(oncheck); SHOW_ATTR(filterset); SHOW_ATTR(disable); /* Print out all the config settings */ config = noit_conf_get_hash(node, "config"); while(noit_hash_next(config, &iter, &k, &klen, &data)) { nc_printf(ncct, " config::%s: %s\n", k, (const char *)data); } noit_hash_destroy(config, free, free); free(config); check = noit_poller_lookup(checkid); if(!check) { nc_printf(ncct, " ERROR: not in running system\n"); } else { int idx = 0; nc_printf(ncct, " currently: "); if(NOIT_CHECK_RUNNING(check)) nc_printf(ncct, "%srunning", idx++?",":""); if(NOIT_CHECK_KILLED(check)) nc_printf(ncct, "%skilled", idx++?",":""); if(!NOIT_CHECK_CONFIGURED(check)) nc_printf(ncct, "%sunconfig", idx++?",":""); if(NOIT_CHECK_DISABLED(check)) nc_printf(ncct, "%sdisabled", idx++?",":""); if(!idx) nc_printf(ncct, "idle"); nc_write(ncct, "\n", 1); if(check->stats.current.whence.tv_sec == 0) { nc_printf(ncct, " last run: never\n"); } else { stats_t *c = &check->stats.current; struct timeval now, diff; gettimeofday(&now, NULL); sub_timeval(now, c->whence, &diff); nc_printf(ncct, " last run: %0.3f seconds ago\n", diff.tv_sec + (diff.tv_usec / 1000000.0)); nc_printf(ncct, " availability/state: %s/%s\n", noit_check_available_string(c->available), noit_check_state_string(c->state)); nc_printf(ncct, " status: %s\n", c->status ? c->status : "[[null]]"); nc_printf(ncct, " metrics:\n"); memset(&iter, 0, sizeof(iter)); while(noit_hash_next(&c->metrics, &iter, &k, &klen, &data)) { char buff[256]; noit_boolean filtered; noit_stats_snprint_metric(buff, sizeof(buff), (metric_t *)data); filtered = !noit_apply_filterset(check->filterset, check, (metric_t *)data); nc_printf(ncct, " %c%s\n", filtered ? '*' : ' ', buff); } } } } out: if(pobj) xmlXPathFreeObject(pobj); return 0; }
int stratcon_line_to_javascript(noit_http_session_ctx *ctx, char *in_buff, u_int32_t *inc_id) { char buffer[1024]; char *scp, *ecp, *token, *buff; int i, len, cnt; const char *v, *cb = NULL; noit_hash_table json = NOIT_HASH_EMPTY; noit_http_request *req = noit_http_session_request(ctx); char s_inc_id[42]; char **outrows = NULL; cb = noit_http_request_querystring(req, "cb"); for(v = cb; v && *v; v++) if(!((*v >= '0' && *v <= '9') || (*v >= 'a' && *v <= 'z') || (*v >= 'A' && *v <= 'Z') || (*v == '_') || (*v == '.'))) { cb = NULL; break; } if(!cb) cb = "window.parent.plot_iframe_data"; #define BAIL_HTTP_WRITE do { \ if(outrows) { \ for(i=0;i<cnt;i++) if(outrows[i]) free(outrows[i]); \ free(outrows); \ } \ noit_hash_destroy(&json, NULL, free); \ noitL(noit_error, "javascript emit failed: %s:%s:%d\n", \ __FILE__, __FUNCTION__, __LINE__); \ return -1; \ } while(0) #define PROCESS_NEXT_FIELD(t,l) do { \ if(!*scp) goto bad_row; \ ecp = strchr(scp, '\t'); \ if(!ecp) goto bad_row; \ t = scp; \ l = (ecp-scp); \ scp = ecp + 1; \ } while(0) #define PROCESS_LAST_FIELD(t,l) do { \ if(!*scp) ecp = scp; \ else { \ ecp = scp + strlen(scp); /* Puts us at the '\0' */ \ if(*(ecp-1) == '\n') ecp--; /* We back up on letter if we ended in \n */ \ } \ t = scp; \ l = (ecp-scp); \ } while(0) noitL(noit_error, "recv(%s)\n", in_buff); if(in_buff[0] == 'B' && in_buff[1] != '\0' && in_buff[2] == '\t') { cnt = noit_check_log_b_to_sm(in_buff, strlen(in_buff), &outrows); } else { cnt = 1; outrows = malloc(sizeof(*outrows)); outrows[0] = strdup(in_buff); } for(i=0; i<cnt; i++) { buff = outrows[i]; if(!buff) continue; noitL(noit_error, "recv_xlt(%s)\n", buff); scp = buff; PROCESS_NEXT_FIELD(token,len); /* Skip the leader */ if(buff[1] == '\t' && (buff[0] == 'M' || buff[0] == 'S')) { char target[256], module[256], name[256], uuid_str[UUID_STR_LEN+1]; noit_http_request *req = noit_http_session_request(ctx); noit_hash_table *qs; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *key; int klen, i=0; void *vval; char type[2] = { '\0', '\0' }; type[0] = buff[0]; #define ra_write(a,b) if(noit_http_response_append(ctx, a, b) == noit_false) BAIL_HTTP_WRITE snprintf(s_inc_id, sizeof(s_inc_id), "script-%08x", (*inc_id)++); snprintf(buffer, sizeof(buffer), "<script id=\"%s\">%s({", s_inc_id, cb); ra_write(buffer, strlen(buffer)); qs = noit_http_request_querystring_table(req); while(noit_hash_next(qs, &iter, &key, &klen, &vval)) { if(!strcmp(key, "cb")) continue; noit_hash_store(&json, key, klen, strdup(vval ?(char *)vval : "true")); } /* Time */ noit_hash_store(&json, "script_id", 9, strdup(s_inc_id)); noit_hash_store(&json, "type", 4, strdup(type)); PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "time", 4, noit__strndup(token, len)); /* UUID */ PROCESS_NEXT_FIELD(token,len); noit_check_extended_id_split(token, len, target, sizeof(target), module, sizeof(module), name, sizeof(name), uuid_str, sizeof(uuid_str)); if(*uuid_str) noit_hash_store(&json, "id", 2, noit__strndup(uuid_str, strlen(uuid_str))); if(*target) noit_hash_store(&json, "check_target", 12, noit__strndup(target, strlen(target))); if(*module) noit_hash_store(&json, "check_module", 12, noit__strndup(module, strlen(module))); if(*name) noit_hash_store(&json, "check_name", 10, noit__strndup(name, strlen(name))); if(buff[0] == 'M') { /* name */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "metric_name", 11, noit__strndup(token, len)); /* type */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "metric_type", 11, noit__strndup(token, len)); /* value */ PROCESS_LAST_FIELD(token,len); /* value */ noit_hash_store(&json, "value", 5, noit__strndup(token, len)); } else if(buff[0] == 'S') { /* state */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "check_state", 11, noit__strndup(token, len)); /* availability */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "check_availability", 18, noit__strndup(token, len)); /* duration */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "check_duration_ms", 17, noit__strndup(token, len)); /* status */ PROCESS_LAST_FIELD(token,len); noit_hash_store(&json, "status_message", 14, noit__strndup(token, len)); } memset(&iter, 0, sizeof(iter)); while(noit_hash_next(&json, &iter, &key, &klen, &vval)) { char *val = (char *)vval; if(i++) ra_write(",", 1); ra_write("\"", 1); ra_write(key, klen); ra_write("\":\"", 3); while(*val) { if(*val == '\"' || *val == '\\') { ra_write((char *)"\\", 1); } if(isprint(*val)) { ra_write((char *)val, 1); } else { char od[5]; snprintf(od, sizeof(od), "\\%03o", *((unsigned char *)val)); ra_write(od, strlen(od)); } val++; } ra_write("\"", 1); } snprintf(buffer, sizeof(buffer), "});</script>\n"); ra_write(buffer, strlen(buffer)); if(noit_http_response_flush(ctx, noit_false) == noit_false) BAIL_HTTP_WRITE; } noit_hash_destroy(&json, NULL, free); memset(&json, 0, sizeof(json)); } if(outrows) { for(i=0;i<cnt;i++) if(outrows[i]) free(outrows[i]); free(outrows); } return 0; bad_row: BAIL_HTTP_WRITE; }
static int rest_show_check(noit_http_rest_closure_t *restc, int npats, char **pats) { noit_http_session_ctx *ctx = restc->http_ctx; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; xmlDocPtr doc = NULL; xmlNodePtr node, root, attr, config, state, tmp, anode; uuid_t checkid; noit_check_t *check; char xpath[1024], *uuid_conf, *module, *value; int rv, cnt, error_code = 500; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; noit_hash_table *configh; if(npats != 2) goto error; rv = noit_check_xpath(xpath, sizeof(xpath), pats[0], pats[1]); if(rv == 0) goto not_found; if(rv < 0) goto error; noit_conf_xml_xpath(NULL, &xpath_ctxt); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET || xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto not_found; cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); if(cnt != 1) goto error; node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid"); if(!uuid_conf || uuid_parse(uuid_conf, checkid)) goto error; doc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(doc, NULL, (xmlChar *)"check", NULL); xmlDocSetRootElement(doc, root); #define MYATTR(node,a,n,b) _noit_conf_get_string(node, &(n), "@" #a, &(b)) #define INHERIT(node,a,n,b) \ _noit_conf_get_string(node, &(n), "ancestor-or-self::node()/@" #a, &(b)) #define SHOW_ATTR(parent, node, a) do { \ xmlNodePtr anode = NULL; \ char *value = NULL; \ INHERIT(node, a, anode, value); \ if(value != NULL) { \ int clen, plen;\ const char *cpath, *apath; \ xmlNodePtr child; \ cpath = node ? (char *)xmlGetNodePath(node) : ""; \ apath = anode ? (char *)xmlGetNodePath(anode) : ""; \ clen = strlen(cpath); \ plen = strlen("/noit/checks"); \ child = xmlNewNode(NULL, (xmlChar *)#a); \ xmlNodeAddContent(child, (xmlChar *)value); \ if(!strncmp(cpath, apath, clen) && apath[clen] == '/') { \ } \ else { \ xmlSetProp(child, (xmlChar *)"inherited", (xmlChar *)apath+plen); \ } \ xmlAddChild(parent, child); \ } \ } while(0) attr = xmlNewNode(NULL, (xmlChar *)"attributes"); xmlAddChild(root, attr); SHOW_ATTR(attr,node,uuid); /* Name is odd, it falls back transparently to module */ if(!INHERIT(node, module, tmp, module)) module = NULL; xmlAddChild(attr, (tmp = xmlNewNode(NULL, (xmlChar *)"name"))); if(MYATTR(node, name, anode, value)) xmlNodeAddContent(tmp, (xmlChar *)value); else if(module) xmlNodeAddContent(tmp, (xmlChar *)module); SHOW_ATTR(attr,node,module); SHOW_ATTR(attr,node,target); SHOW_ATTR(attr,node,period); SHOW_ATTR(attr,node,timeout); SHOW_ATTR(attr,node,oncheck); SHOW_ATTR(attr,node,filterset); SHOW_ATTR(attr,node,disable); /* Add the config */ config = xmlNewNode(NULL, (xmlChar *)"config"); configh = noit_conf_get_hash(node, "config"); while(noit_hash_next(configh, &iter, &k, &klen, &data)) NODE_CONTENT(config, k, data); noit_hash_destroy(configh, free, free); free(configh); xmlAddChild(root, config); /* Add the state */ check = noit_poller_lookup(checkid); if(!check) { state = xmlNewNode(NULL, (xmlChar *)"state"); xmlSetProp(state, (xmlChar *)"error", (xmlChar *)"true"); } else state = noit_check_state_as_xml(check); xmlAddChild(root, state); noit_http_response_ok(ctx, "text/xml"); noit_http_response_xml(ctx, doc); noit_http_response_end(ctx); goto cleanup; not_found: noit_http_response_not_found(ctx, "text/html"); noit_http_response_end(ctx); goto cleanup; error: noit_http_response_standard(ctx, error_code, "ERROR", "text/html"); noit_http_response_end(ctx); goto cleanup; cleanup: if(pobj) xmlXPathFreeObject(pobj); if(doc) xmlFreeDoc(doc); return 0; }
static void noit_capabilities_tobuff(noit_capsvc_closure_t *cl, eventer_func_t curr) { const char **mod_names; struct utsname utsn; char vbuff[128], bwstr[4]; noit_hash_table *lc; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen, i, nmods; void *data; struct timeval now; xmlDocPtr xmldoc; xmlNodePtr root, cmds, bi, ri, mods, feat; /* fill out capabilities */ /* Create an XML Document */ xmldoc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(xmldoc, NULL, (xmlChar *)"noit_capabilities", NULL); xmlDocSetRootElement(xmldoc, root); /* Fill in the document */ noit_build_version(vbuff, sizeof(vbuff)); xmlNewTextChild(root, NULL, (xmlChar *)"version", (xmlChar *)vbuff); snprintf(bwstr, sizeof(bwstr), "%d", (int)sizeof(void *)*8); /* Build info */ bi = xmlNewNode(NULL, (xmlChar *)"unameBuild"); xmlSetProp(bi, (xmlChar *)"bitwidth", (xmlChar *)bwstr); xmlAddChild(root, bi); xmlNewTextChild(bi, NULL, (xmlChar *)"sysname", (xmlChar *)UNAME_S); xmlNewTextChild(bi, NULL, (xmlChar *)"nodename", (xmlChar *)UNAME_N); xmlNewTextChild(bi, NULL, (xmlChar *)"release", (xmlChar *)UNAME_R); xmlNewTextChild(bi, NULL, (xmlChar *)"version", (xmlChar *)UNAME_V); xmlNewTextChild(bi, NULL, (xmlChar *)"machine", (xmlChar *)UNAME_M); /* Run info */ ri = xmlNewNode(NULL, (xmlChar *)"unameRun"); xmlSetProp(ri, (xmlChar *)"bitwidth", (xmlChar *)bwstr); xmlAddChild(root, ri); if(uname(&utsn)) { xmlNewTextChild(ri, NULL, (xmlChar *)"error", (xmlChar *)strerror(errno)); } else { xmlNewTextChild(ri, NULL, (xmlChar *)"sysname", (xmlChar *)utsn.sysname); xmlNewTextChild(ri, NULL, (xmlChar *)"nodename", (xmlChar *)utsn.nodename); xmlNewTextChild(ri, NULL, (xmlChar *)"release", (xmlChar *)utsn.release); xmlNewTextChild(ri, NULL, (xmlChar *)"version", (xmlChar *)utsn.version); xmlNewTextChild(ri, NULL, (xmlChar *)"machine", (xmlChar *)utsn.machine); } /* features */ feat = xmlNewNode(NULL, (xmlChar *)"features"); xmlAddChild(root, feat); if(features.size) { noit_hash_iter iter2 = NOIT_HASH_ITER_ZERO; void *vfv; const char *f; int flen; while(noit_hash_next(&features, &iter2, &f, &flen, &vfv)) { xmlNodePtr featnode; featnode = xmlNewNode(NULL, (xmlChar *)"feature"); xmlSetProp(featnode, (xmlChar *)"name", (xmlChar *)f); if(vfv) xmlSetProp(featnode, (xmlChar *)"version", (xmlChar *)vfv); xmlAddChild(feat, featnode); } } /* time (poor man's time check) */ gettimeofday(&now, NULL); snprintf(vbuff, sizeof(vbuff), "%llu.%03d", (unsigned long long)now.tv_sec, (int)(now.tv_usec / 1000)); xmlNewTextChild(root, NULL, (xmlChar *)"current_time", (xmlChar *)vbuff); cmds = xmlNewNode(NULL, (xmlChar *)"services"); xmlAddChild(root, cmds); lc = noit_listener_commands(); while(noit_hash_next(lc, &iter, &k, &klen, &data)) { xmlNodePtr cnode; char hexcode[11]; const char *name; eventer_func_t *f = (eventer_func_t *)k; noit_hash_table *sc = (noit_hash_table *)data; noit_hash_iter sc_iter = NOIT_HASH_ITER_ZERO; const char *sc_k; int sc_klen; void *sc_data; name = eventer_name_for_callback(*f); cnode = xmlNewNode(NULL, (xmlChar *)"service"); xmlSetProp(cnode, (xmlChar *)"name", name ? (xmlChar *)name : NULL); if(*f == curr) xmlSetProp(cnode, (xmlChar *)"connected", (xmlChar *)"true"); xmlAddChild(cmds, cnode); while(noit_hash_next(sc, &sc_iter, &sc_k, &sc_klen, &sc_data)) { xmlNodePtr scnode; char *name_copy, *version = NULL; eventer_func_t *f = (eventer_func_t *)sc_data; snprintf(hexcode, sizeof(hexcode), "0x%08x", *((u_int32_t *)sc_k)); name = eventer_name_for_callback(*f); name_copy = strdup(name ? name : "[[unknown]]"); version = strchr(name_copy, '/'); if(version) *version++ = '\0'; scnode = xmlNewNode(NULL, (xmlChar *)"command"); xmlSetProp(scnode, (xmlChar *)"name", (xmlChar *)name_copy); if(version) xmlSetProp(scnode, (xmlChar *)"version", (xmlChar *)version); xmlSetProp(scnode, (xmlChar *)"code", (xmlChar *)hexcode); xmlAddChild(cnode, scnode); free(name_copy); } } mods = xmlNewNode(NULL, (xmlChar *)"modules"); xmlAddChild(root, mods); #define list_modules(func, name) do { \ nmods = func(&mod_names); \ for(i=0; i<nmods; i++) { \ xmlNodePtr pnode; \ pnode = xmlNewNode(NULL, (xmlChar *)"module"); \ xmlSetProp(pnode, (xmlChar *)"type", (xmlChar *)name); \ xmlSetProp(pnode, (xmlChar *)"name", (xmlChar *)mod_names[i]); \ xmlAddChild(mods, pnode); \ } \ if(mod_names) free(mod_names); \ } while(0) list_modules(noit_module_list_loaders, "loader"); list_modules(noit_module_list_modules, "module"); list_modules(noit_module_list_generics, "generic"); /* Write it out to a buffer and copy it for writing */ cl->buff = noit_xmlSaveToBuffer(xmldoc); cl->towrite = strlen(cl->buff); /* Clean up after ourselves */ xmlFreeDoc(xmldoc); }
static void noit_capabilities_tobuff_json(noit_capsvc_closure_t *cl, eventer_func_t curr) { const char **mod_names; struct utsname utsn; char vbuff[128]; noit_hash_table *lc; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen, i, nmods; void *data; struct timeval now; struct json_object *doc; struct json_object *svcs, *bi, *ri, *mods, *feat; /* fill out capabilities */ /* Create an XML Document */ doc = json_object_new_object(); /* Fill in the document */ noit_build_version(vbuff, sizeof(vbuff)); json_object_object_add(doc, "version", json_object_new_string(vbuff)); /* Build info */ bi = json_object_new_object(); json_object_object_add(bi, "bitwidth", json_object_new_int(sizeof(void *)*8)); json_object_object_add(bi, "sysname", json_object_new_string(UNAME_S)); json_object_object_add(bi, "nodename", json_object_new_string(UNAME_N)); json_object_object_add(bi, "release", json_object_new_string(UNAME_R)); json_object_object_add(bi, "version", json_object_new_string(UNAME_V)); json_object_object_add(bi, "machine", json_object_new_string(UNAME_M)); json_object_object_add(doc, "unameBuild", bi); /* Run info */ ri = json_object_new_object(); json_object_object_add(ri, "bitwidth", json_object_new_int(sizeof(void *)*8)); if(uname(&utsn)) { json_object_object_add(ri, "error", json_object_new_string(strerror(errno))); } else { json_object_object_add(ri, "sysname", json_object_new_string(utsn.sysname)); json_object_object_add(ri, "nodename", json_object_new_string(utsn.nodename)); json_object_object_add(ri, "release", json_object_new_string(utsn.release)); json_object_object_add(ri, "version", json_object_new_string(utsn.version)); json_object_object_add(ri, "machine", json_object_new_string(utsn.machine)); } json_object_object_add(doc, "unameRun", ri); /* features */ feat = json_object_new_object(); if(features.size) { noit_hash_iter iter2 = NOIT_HASH_ITER_ZERO; void *vfv; const char *f; int flen; while(noit_hash_next(&features, &iter2, &f, &flen, &vfv)) { struct json_object *featnode; featnode = json_object_new_object(); if(vfv) json_object_object_add(featnode, "version", json_object_new_string(vfv)); json_object_object_add(feat, f, featnode); } } json_object_object_add(doc, "features", feat); /* time (poor man's time check) */ gettimeofday(&now, NULL); snprintf(vbuff, sizeof(vbuff), "%llu%03d", (unsigned long long)now.tv_sec, (int)(now.tv_usec / 1000)); json_object_object_add(doc, "current_time", json_object_new_string(vbuff)); svcs = json_object_new_object(); lc = noit_listener_commands(); while(noit_hash_next(lc, &iter, &k, &klen, &data)) { struct json_object *cnode, *cmds; char hexcode[11]; const char *name; eventer_func_t *f = (eventer_func_t *)k; noit_hash_table *sc = (noit_hash_table *)data; noit_hash_iter sc_iter = NOIT_HASH_ITER_ZERO; const char *sc_k; int sc_klen; void *sc_data; name = eventer_name_for_callback(*f); cnode = json_object_new_object(); if(klen == 8) snprintf(hexcode, sizeof(hexcode), "0x%0llx", (unsigned long long int)(vpsized_uint)**f); else snprintf(hexcode, sizeof(hexcode), "0x%0x", (unsigned int)(vpsized_uint)**f); json_object_object_add(svcs, hexcode, cnode); if(name) json_object_object_add(cnode, name, json_object_new_string(name)); cmds = json_object_new_object(); json_object_object_add(cnode, "commands", cmds); while(noit_hash_next(sc, &sc_iter, &sc_k, &sc_klen, &sc_data)) { struct json_object *scnode; char *name_copy, *version = NULL; eventer_func_t *f = (eventer_func_t *)sc_data; scnode = json_object_new_object(); snprintf(hexcode, sizeof(hexcode), "0x%08x", *((u_int32_t *)sc_k)); name = eventer_name_for_callback(*f); name_copy = strdup(name ? name : "[[unknown]]"); version = strchr(name_copy, '/'); if(version) *version++ = '\0'; json_object_object_add(scnode, "name", json_object_new_string(name_copy)); if(version) json_object_object_add(scnode, "version", json_object_new_string(version)); json_object_object_add(cmds, hexcode, scnode); free(name_copy); } } json_object_object_add(doc, "services", svcs); mods = json_object_new_object(); #define list_modules_json(func, name) do { \ nmods = func(&mod_names); \ for(i=0; i<nmods; i++) { \ struct json_object *pnode; \ pnode = json_object_new_object(); \ json_object_object_add(pnode, "type", json_object_new_string(name)); \ json_object_object_add(mods, mod_names[i], pnode); \ } \ if(mod_names) free(mod_names); \ } while(0) list_modules_json(noit_module_list_loaders, "loader"); list_modules_json(noit_module_list_modules, "module"); list_modules_json(noit_module_list_generics, "generic"); json_object_object_add(doc, "modules", mods); /* Write it out to a buffer and copy it for writing */ cl->buff = strdup(json_object_to_json_string(doc)); cl->towrite = strlen(cl->buff); /* Clean up after ourselves */ json_object_put(doc); }
static void noit_capabilities_tobuff(noit_capsvc_closure_t *cl, eventer_func_t curr) { char vbuff[128]; noit_hash_table *lc; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; struct timeval now; xmlDocPtr xmldoc; xmlNodePtr root, cmds; /* fill out capabilities */ /* Create an XML Document */ xmldoc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(xmldoc, NULL, (xmlChar *)"noit_capabilities", NULL); xmlDocSetRootElement(xmldoc, root); /* Fill in the document */ noit_build_version(vbuff, sizeof(vbuff)); xmlNewTextChild(root, NULL, (xmlChar *)"version", (xmlChar *)vbuff); /* time (poor man's time check) */ gettimeofday(&now, NULL); snprintf(vbuff, sizeof(vbuff), "%llu.%03d", (unsigned long long)now.tv_sec, (int)(now.tv_usec / 1000)); xmlNewTextChild(root, NULL, (xmlChar *)"current_time", (xmlChar *)vbuff); cmds = xmlNewNode(NULL, (xmlChar *)"services"); xmlAddChild(root, cmds); lc = noit_listener_commands(); while(noit_hash_next(lc, &iter, &k, &klen, &data)) { xmlNodePtr cnode; char hexcode[11]; const char *name; eventer_func_t *f = (eventer_func_t *)k; noit_hash_table *sc = (noit_hash_table *)data; noit_hash_iter sc_iter = NOIT_HASH_ITER_ZERO; const char *sc_k; int sc_klen; void *sc_data; name = eventer_name_for_callback(*f); cnode = xmlNewNode(NULL, (xmlChar *)"service"); xmlSetProp(cnode, (xmlChar *)"name", name ? (xmlChar *)name : NULL); if(*f == curr) xmlSetProp(cnode, (xmlChar *)"connected", (xmlChar *)"true"); xmlAddChild(cmds, cnode); while(noit_hash_next(sc, &sc_iter, &sc_k, &sc_klen, &sc_data)) { xmlNodePtr scnode; char *name_copy, *version = NULL; eventer_func_t *f = (eventer_func_t *)sc_data; snprintf(hexcode, sizeof(hexcode), "0x%08x", *((u_int32_t *)sc_k)); name = eventer_name_for_callback(*f); name_copy = strdup(name ? name : "[[unknown]]"); version = strchr(name_copy, '/'); if(version) *version++ = '\0'; scnode = xmlNewNode(NULL, (xmlChar *)"command"); xmlSetProp(scnode, (xmlChar *)"name", (xmlChar *)name_copy); if(version) xmlSetProp(scnode, (xmlChar *)"version", (xmlChar *)version); xmlSetProp(scnode, (xmlChar *)"code", (xmlChar *)hexcode); xmlAddChild(cnode, scnode); free(name_copy); } } /* Write it out to a buffer and copy it for writing */ cl->buff = noit_xmlSaveToBuffer(xmldoc); cl->towrite = strlen(cl->buff); /* Clean up after ourselves */ xmlFreeDoc(xmldoc); }
int noit_capabilities_handler(eventer_t e, int mask, void *closure, struct timeval *now) { int newmask = EVENTER_WRITE | EVENTER_EXCEPTION; acceptor_closure_t *ac = closure; noit_capsvc_closure_t *cl = ac->service_ctx; if(mask & EVENTER_EXCEPTION) { socket_error: /* Exceptions cause us to simply snip the connection */ cleanup_shutdown: eventer_remove_fd(e->fd); e->opset->close(e->fd, &newmask, e); if(cl) { if(cl->buff) free(cl->buff); free(cl); } if(ac) acceptor_closure_free(ac); return 0; } if(!ac->service_ctx) { char vbuff[128]; noit_hash_table *lc; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; xmlDocPtr xmldoc; xmlNodePtr root, cmds; cl = ac->service_ctx = calloc(1, sizeof(*cl)); /* fill out capabilities */ noit_build_version(vbuff, sizeof(vbuff)); /* Create an XML Document */ xmldoc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(xmldoc, NULL, (xmlChar *)"noit_capabilities", NULL); xmlDocSetRootElement(xmldoc, root); /* Fill in the document */ xmlNewTextChild(root, NULL, (xmlChar *)"version", (xmlChar *)vbuff); cmds = xmlNewNode(NULL, (xmlChar *)"services"); xmlAddChild(root, cmds); lc = noit_listener_commands(); while(noit_hash_next(lc, &iter, &k, &klen, &data)) { xmlNodePtr cnode; char hexcode[11]; const char *name; eventer_func_t *f = (eventer_func_t *)k; noit_hash_table *sc = (noit_hash_table *)data; noit_hash_iter sc_iter = NOIT_HASH_ITER_ZERO; const char *sc_k; int sc_klen; void *sc_data; name = eventer_name_for_callback(*f); cnode = xmlNewNode(NULL, (xmlChar *)"service"); xmlSetProp(cnode, (xmlChar *)"name", name ? (xmlChar *)name : NULL); if(*f == ac->dispatch) xmlSetProp(cnode, (xmlChar *)"connected", (xmlChar *)"true"); xmlAddChild(cmds, cnode); while(noit_hash_next(sc, &sc_iter, &sc_k, &sc_klen, &sc_data)) { xmlNodePtr scnode; char *name_copy, *version = NULL; eventer_func_t *f = (eventer_func_t *)sc_data; snprintf(hexcode, sizeof(hexcode), "0x%08x", *((u_int32_t *)sc_k)); name = eventer_name_for_callback(*f); name_copy = strdup(name ? name : "[[unknown]]"); version = strchr(name_copy, '/'); if(version) *version++ = '\0'; scnode = xmlNewNode(NULL, (xmlChar *)"command"); xmlSetProp(scnode, (xmlChar *)"name", (xmlChar *)name_copy); if(version) xmlSetProp(scnode, (xmlChar *)"version", (xmlChar *)version); xmlSetProp(scnode, (xmlChar *)"code", (xmlChar *)hexcode); xmlAddChild(cnode, scnode); free(name_copy); } } /* Write it out to a buffer and copy it for writing */ cl->buff = noit_xmlSaveToBuffer(xmldoc); cl->towrite = strlen(cl->buff); /* Clean up after ourselves */ xmlFreeDoc(xmldoc); } while(cl->towrite > cl->written) { int len; while((len = e->opset->write(e->fd, cl->buff + cl->written, cl->towrite - cl->written, &newmask, e)) == -1 && errno == EINTR); if(len < 0) { if(errno == EAGAIN) return newmask | EVENTER_EXCEPTION; goto socket_error; } cl->written += len; } goto cleanup_shutdown; }
int noit_check_update(noit_check_t *new_check, const char *target, const char *name, const char *filterset, noit_hash_table *config, u_int32_t period, u_int32_t timeout, const char *oncheck, int flags) { int8_t family; int rv; int mask = NP_DISABLED | NP_UNCONFIG; union { struct in_addr addr4; struct in6_addr addr6; } a; family = AF_INET; rv = inet_pton(family, target, &a); if(rv != 1) { family = AF_INET6; rv = inet_pton(family, target, &a); if(rv != 1) { noitL(noit_stderr, "Cannot translate '%s' to IP\n", target); memset(&a, 0, sizeof(a)); flags |= (NP_UNCONFIG | NP_DISABLED); } } new_check->generation = __config_load_generation; new_check->target_family = family; memcpy(&new_check->target_addr, &a, sizeof(a)); if(new_check->target) free(new_check->target); new_check->target = strdup(target); if(new_check->name) free(new_check->name); new_check->name = name ? strdup(name): NULL; if(new_check->filterset) free(new_check->filterset); new_check->filterset = filterset ? strdup(filterset): NULL; if(config != NULL) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; if(new_check->config) noit_hash_delete_all(new_check->config, free, free); else new_check->config = calloc(1, sizeof(*new_check->config)); while(noit_hash_next(config, &iter, &k, &klen, &data)) { noit_hash_store(new_check->config, strdup(k), klen, strdup((char *)data)); } } if(new_check->oncheck) free(new_check->oncheck); new_check->oncheck = oncheck ? strdup(oncheck) : NULL; new_check->period = period; new_check->timeout = timeout; /* Unset what could be set.. then set what should be set */ new_check->flags = (new_check->flags & ~mask) | flags; if(!(new_check->flags & NP_TRANSIENT)) { /* This remove could fail -- no big deal */ noit_skiplist_remove(&polls_by_name, new_check, NULL); /* This insert could fail.. which means we have a conflict on * target`name. That should result in the check being disabled. */ if(!noit_skiplist_insert(&polls_by_name, new_check)) { noitL(noit_stderr, "Check %s`%s disabled due to naming conflict\n", new_check->target, new_check->name); new_check->flags |= NP_DISABLED; } } noit_check_log_check(new_check); return 0; }
int stratcon_line_to_javascript(noit_http_session_ctx *ctx, char *buff, u_int32_t inc_id) { char buffer[1024]; char *scp, *ecp, *token; int len; void *vcb; const char *v, *cb = NULL; noit_hash_table json = NOIT_HASH_EMPTY; char s_inc_id[42]; snprintf(s_inc_id, sizeof(s_inc_id), "script-%08x", inc_id); if(noit_hash_retrieve(&ctx->req.querystring, "cb", strlen("cb"), &vcb)) cb = vcb; for(v = cb; v && *v; v++) if(!((*v >= '0' && *v <= '9') || (*v >= 'a' && *v <= 'z') || (*v >= 'A' && *v <= 'Z') || (*v == '_') || (*v == '.'))) { cb = NULL; break; } if(!cb) cb = "window.parent.plot_iframe_data"; #define BAIL_HTTP_WRITE do { \ noit_hash_destroy(&json, NULL, free); \ noitL(noit_error, "javascript emit failed: %s:%s:%d\n", \ __FILE__, __FUNCTION__, __LINE__); \ return -1; \ } while(0) #define PROCESS_NEXT_FIELD(t,l) do { \ if(!*scp) goto bad_row; \ ecp = strchr(scp, '\t'); \ if(!ecp) goto bad_row; \ t = scp; \ l = (ecp-scp); \ scp = ecp + 1; \ } while(0) #define PROCESS_LAST_FIELD(t,l) do { \ if(!*scp) ecp = scp; \ else { \ ecp = scp + strlen(scp); /* Puts us at the '\0' */ \ if(*(ecp-1) == '\n') ecp--; /* We back up on letter if we ended in \n */ \ } \ t = scp; \ l = (ecp-scp); \ } while(0) scp = buff; PROCESS_NEXT_FIELD(token,len); /* Skip the leader */ if(buff[0] == 'M') { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *key; int klen, i=0; void *vval; #define ra_write(a,b) if(noit_http_response_append(ctx, a, b) == noit_false) BAIL_HTTP_WRITE snprintf(buffer, sizeof(buffer), "<script id=\"%s\">%s({", s_inc_id, cb); ra_write(buffer, strlen(buffer)); while(noit_hash_next(&ctx->req.querystring, &iter, &key, &klen, &vval)) { if(!strcmp(key, "cb")) continue; noit_hash_store(&json, key, klen, strdup(vval ?(char *)vval : "true")); } /* Time */ noit_hash_store(&json, "script_id", 9, strdup(s_inc_id)); noit_hash_store(&json, "type", 4, strdup("M")); PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "time", 4, noit__strndup(token, len)); /* UUID */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "id", 2, noit__strndup(token, len)); /* name */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "metric_name", 11, noit__strndup(token, len)); /* type */ PROCESS_NEXT_FIELD(token,len); noit_hash_store(&json, "metric_type", 11, noit__strndup(token, len)); /* value */ PROCESS_LAST_FIELD(token,len); /* value */ noit_hash_store(&json, "value", 5, noit__strndup(token, len)); memset(&iter, 0, sizeof(iter)); while(noit_hash_next(&json, &iter, &key, &klen, &vval)) { char *val = (char *)vval; if(i++) ra_write(",", 1); ra_write("'", 1); ra_write(key, klen); ra_write("':\"", 3); while(*val) { if(*val == '\"' || *val == '\\') { ra_write((char *)"\\", 1); } if(isprint(*val)) { ra_write((char *)val, 1); } else { char od[5]; snprintf(od, sizeof(od), "\\%03o", *((unsigned char *)val)); ra_write(od, strlen(od)); } val++; } ra_write("\"", 1); } snprintf(buffer, sizeof(buffer), "});</script>\n"); ra_write(buffer, strlen(buffer)); if(noit_http_response_flush(ctx, noit_false) == noit_false) BAIL_HTTP_WRITE; } noit_hash_destroy(&json, NULL, free); return 0; bad_row: BAIL_HTTP_WRITE; }