static int lua_general_reverse_socket_initiate(lua_State *L) { const char *host; int port; mtev_hash_table *sslconfig = NULL, *config = NULL; if(lua_gettop(L) < 2 || !lua_isstring(L,1) || !lua_isnumber(L,2) || (lua_gettop(L) >= 3 && !lua_istable(L,3)) || (lua_gettop(L) >= 4 && !lua_istable(L,4))) luaL_error(L, "reverse_start(host,port,sslconfig,config)"); host = lua_tostring(L,1); port = lua_tointeger(L,2); if(lua_gettop(L)>=3) sslconfig = mtev_lua_table_to_hash(L,3); if(lua_gettop(L)>=4) config = mtev_lua_table_to_hash(L,4); mtev_lua_help_initiate_mtev_connection(host, port, sslconfig, config); if(sslconfig) { mtev_hash_destroy(sslconfig, NULL, NULL); free(sslconfig); } if(config) { mtev_hash_destroy(config, NULL, NULL); free(config); } return 0; }
static mtev_hash_table * get_dedupe_hash(uint64_t whence) { struct hash_and_time *hash_with_time; mtev_hash_table *hash; if (mtev_hash_retrieve(&dedupe_hashes, (const char *)&whence, sizeof(whence), (void **)&hash_with_time) == 1) { hash = &hash_with_time->hash; } else { hash_with_time = calloc(1, sizeof(struct hash_and_time)); mtev_hash_init_locks(&hash_with_time->hash, MTEV_HASH_DEFAULT_SIZE, MTEV_HASH_LOCK_MODE_MUTEX); uint64_t *stored_ts = calloc(1, sizeof(uint64_t)); *stored_ts = whence; if (mtev_hash_store(&dedupe_hashes, (const char *)stored_ts, sizeof(*stored_ts), hash_with_time) == 0) { /* ugh, someone beat us */ free(stored_ts); mtev_hash_destroy(&hash_with_time->hash, NULL, NULL); free(hash_with_time); if (mtev_hash_retrieve(&dedupe_hashes, (const char *)&whence, sizeof(whence), (void **)&hash_with_time) == 0) { return NULL; } } hash = &hash_with_time->hash; } hash_with_time->last_touched_s = mtev_gethrtime() / 1000000000; return hash; }
static int do_test(mtev_hash_lock_mode_t lock_mode) { mtev_hash_table hash; mtev_hash_init_locks(&hash, 400, lock_mode); pthread_t threads[THREAD_COUNT]; for (int i = 0; i < THREAD_COUNT; i++) { pthread_create(&threads[i], NULL, thread_func, &hash); } for (int i = 0; i < THREAD_COUNT; i++) { pthread_join(threads[i], NULL); } mtev_hash_iter iter = MTEV_HASH_ITER_ZERO; const char *k; int klen; void *data; while(mtev_hash_next(&hash, &iter, &k, &klen, &data)) { printf("%s\n", k); } mtev_hash_destroy(&hash, free, NULL); return 0; }
static int prune_old_dedupe_hashes(eventer_t e, int mask, void *unused, struct timeval *now) { mtev_hash_iter iter = MTEV_HASH_ITER_ZERO; uint64_t now_hrtime = mtev_gethrtime() / 1000000000; const char *k; int klen; void *data; struct hash_and_time *hash_with_time; struct removable_hashes { uint64_t key; struct hash_and_time *data; struct removable_hashes *next; }; struct removable_hashes *head = NULL; struct removable_hashes *tail = NULL; /* build a list of expirable items */ while(mtev_hash_next(&dedupe_hashes, &iter, &k, &klen, &data)) { hash_with_time = data; if (now_hrtime > hash_with_time->last_touched_s && now_hrtime - hash_with_time->last_touched_s > 10) { struct removable_hashes *h = calloc(1, sizeof(struct removable_hashes)); h->key = *(uint64_t *)k; h->data = hash_with_time; if (tail != NULL) { tail->next = h; } tail = h; if (head == NULL) { head = tail; } } } /* expire them */ while (head != NULL) { mtev_hash_delete(&dedupe_hashes, (const char *)&head->key, sizeof(head->key), free, NULL); mtev_hash_destroy(&head->data->hash, free, NULL); free(head->data); struct removable_hashes *prev = head; head = head->next; free(prev); } e->whence.tv_sec = now->tv_sec + 5; return 1; }
static int mtev_httptrap_config(noit_module_t *self, mtev_hash_table *options) { httptrap_mod_config_t *conf; conf = noit_module_get_userdata(self); if(conf) { if(conf->options) { mtev_hash_destroy(conf->options, free, free); free(conf->options); } } else conf = calloc(1, sizeof(*conf)); conf->options = options; noit_module_set_userdata(self, conf); return 1; }
static int configure_eventer() { int rv = 0; mtev_hash_table *table; table = mtev_conf_get_hash(NULL, "/" APPNAME "/eventer/config"); if(table) { mtev_hash_iter iter = MTEV_HASH_ITER_ZERO; const char *key, *value; int klen; while(mtev_hash_next_str(table, &iter, &key, &klen, &value)) { int subrv; if((subrv = eventer_propset(key, value)) != 0) rv = subrv; } mtev_hash_destroy(table, free, free); free(table); } return rv; }
static int noit_lua_interpolate(lua_State *L) { noit_check_t *check; mtev_hash_table check_attrs_hash; char buff[8192]; if(lua_gettop(L) != 1) luaL_error(L, "wrong number of arguments"); check = lua_touserdata(L, lua_upvalueindex(1)); if(!lua_isstring(L,1) && !lua_istable(L,1)) { luaL_error(L, "noit.check.interpolate(<string|table>)"); } noit_check_make_attrs(check, &check_attrs_hash); if(lua_isstring(L,1)) { const char *ns = lua_tostring(L, 1); noit_check_interpolate(buff, sizeof(buff), ns, &check_attrs_hash, check->config); lua_pushstring(L, buff); } else { /* We have a table */ /* And we need a new table to return */ lua_createtable(L, 0, 0); /* push a blank key to prep for lua_next calls */ lua_pushnil(L); while(lua_next(L, -3)) { /* src table is -3 */ const char *key = lua_tostring(L, -2); if(lua_isstring(L, -1)) { const char *ns = lua_tostring(L,-1); noit_check_interpolate(buff, sizeof(buff), ns, &check_attrs_hash, check->config); lua_pop(L,1); lua_pushstring(L, buff); } lua_setfield(L, -3, key); /* tgt table is -3 */ } } mtev_hash_destroy(&check_attrs_hash, NULL, NULL); return 1; }
static int configure_eventer(const char *appname) { int rv = 0; mtev_boolean rlim_found = mtev_false; mtev_hash_table *table; char appscratch[1024]; snprintf(appscratch, sizeof(appscratch), "/%s/eventer/config", appname); table = mtev_conf_get_hash(NULL, appscratch); if(table) { mtev_hash_iter iter = MTEV_HASH_ITER_ZERO; const char *key, *value; int klen; while(mtev_hash_next_str(table, &iter, &key, &klen, &value)) { int subrv; /* We want to set a sane default if the user doesn't provide an * rlim_nofiles value... however, we have to try to set the user * value before we set the default, because otherwise, if snowth * is being run as a non-privileged user and we set a default * lower than the user specified one, we can't raise it. Ergo - * try to set from the config first, then set a default if one * isn't specified */ if ((strlen(key) == strlen("rlim_nofiles")) && (strncmp(key, "rlim_nofiles", strlen(key)) == 0) ) { rlim_found = mtev_true; } if((subrv = eventer_propset(key, value)) != 0) rv = subrv; } mtev_hash_destroy(table, free, free); free(table); } /* If no rlim_nofiles configuration was found, set a default * of (2048*2048) */ if (!rlim_found) { eventer_propset("rlim_nofiles", "4194304"); } return rv; }
static int rest_show_check(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_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 = NULL, *value = NULL; int rv, mod, mod_cnt, cnt, error_code = 500; mtev_hash_iter iter = MTEV_HASH_ITER_ZERO; const char *k; int klen; void *data; mtev_hash_table *configh; if(npats != 2 && npats != 3) goto error; rv = noit_check_xpath(xpath, sizeof(xpath), pats[0], pats[1]); if(rv == 0) goto not_found; if(rv < 0) goto error; mtev_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 = (mtev_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid"); if(!uuid_conf || uuid_parse(uuid_conf, checkid)) goto error; if(npats == 3 && !strcmp(pats[2], ".json")) { return rest_show_check_json(restc, checkid); } doc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(doc, NULL, (xmlChar *)"check", NULL); xmlDocSetRootElement(doc, root); #define MYATTR(node,a,n,b) _mtev_conf_get_string(node, &(n), "@" #a, &(b)) #define INHERIT(node,a,n,b) \ _mtev_conf_get_string(node, &(n), "ancestor-or-self::node()/@" #a, &(b)) #define SHOW_ATTR(parent, node, a) do { \ char *_value = NULL; \ INHERIT(node, a, anode, _value); \ if(_value != NULL) { \ int clen, plen;\ char *_cpath, *_apath; \ xmlNodePtr child; \ _cpath = node ? (char *)xmlGetNodePath(node) : strdup(""); \ _apath = anode ? (char *)xmlGetNodePath(anode) : strdup(""); \ 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); \ free(_cpath); \ free(_apath); \ free(_value); \ } \ } while(0) attr = xmlNewNode(NULL, (xmlChar *)"attributes"); xmlAddChild(root, attr); SHOW_ATTR(attr,node,uuid); SHOW_ATTR(attr,node,seq); /* 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); if(value) free(value); if(module) free(module); SHOW_ATTR(attr,node,module); SHOW_ATTR(attr,node,target); SHOW_ATTR(attr,node,resolve_rtype); SHOW_ATTR(attr,node,seq); 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 = mtev_conf_get_hash(node, "config"); while(mtev_hash_next(configh, &iter, &k, &klen, &data)) NODE_CONTENT(config, k, data); mtev_hash_destroy(configh, free, free); free(configh); mod_cnt = noit_check_registered_module_cnt(); for(mod=0; mod<mod_cnt; mod++) { xmlNsPtr ns; const char *nsname; char buff[256]; nsname = noit_check_registered_module(mod); snprintf(buff, sizeof(buff), "noit://module/%s", nsname); ns = xmlSearchNs(root->doc, root, (xmlChar *)nsname); if(!ns) ns = xmlNewNs(root, (xmlChar *)buff, (xmlChar *)nsname); if(ns) { configh = mtev_conf_get_namespaced_hash(node, "config", nsname); if(configh) { memset(&iter, 0, sizeof(iter)); while(mtev_hash_next(configh, &iter, &k, &klen, &data)) { NS_NODE_CONTENT(config, ns, "value", data, xmlSetProp(tmp, (xmlChar *)"name", (xmlChar *)k); ); } mtev_hash_destroy(configh, free, free); free(configh); } } }
void mtev_dso_init(void) { mtev_conf_section_t *sections; int i, cnt = 0; mtev_dso_add_type("loader", mtev_dso_list_loaders); mtev_dso_add_type("generic", mtev_dso_list_generics); /* Load our generic modules */ sections = mtev_conf_get_sections(MTEV_CONF_ROOT, "//modules//generic", &cnt); for(i=0; i<cnt; i++) { char g_name[256]; mtev_dso_generic_t *gen; mtev_conf_section_t *include_sections = NULL; int section_cnt; if(!mtev_conf_get_stringbuf(sections[i], "ancestor-or-self::node()/@name", g_name, sizeof(g_name))) { mtevL(mtev_stderr, "No name defined in generic stanza %d\n", i+1); continue; } if(mtev_conf_env_off(sections[i], NULL)) { mtevL(mtev_debug, "generic module %s environmentally disabled.\n", g_name); continue; } gen = (mtev_dso_generic_t *) mtev_load_generic_image(&__mtev_image_loader, g_name, sections[i]); if(!gen) { mtevL(mtev_stderr, "Failed to load generic %s\n", g_name); mtev_dso_load_failure_count++; continue; } if(gen->config) { int rv; mtev_hash_table *config; include_sections = mtev_conf_get_sections(sections[i], "include", §ion_cnt); if ((include_sections) && (section_cnt == 1)) { config = mtev_conf_get_hash(*include_sections, "config"); } else { config = mtev_conf_get_hash(sections[i], "config"); } mtev_conf_release_sections(include_sections, section_cnt); rv = gen->config(gen, config); if(rv == 0) { mtev_hash_destroy(config, free, free); free(config); } else if(rv < 0) { mtevL(mtev_stderr, "Failed to config generic %s\n", g_name); continue; } } if(gen->init && gen->init(gen)) { mtevL(mtev_stderr, "Failed to init generic %s\n", g_name); mtev_dso_load_failure_count++; } else mtevL(mtev_debug, "Generic module %s successfully loaded.\n", g_name); } mtev_conf_release_sections(sections, cnt); /* Load our module loaders */ sections = mtev_conf_get_sections(MTEV_CONF_ROOT, "//modules//loader", &cnt); for(i=0; i<cnt; i++) { char loader_name[256]; mtev_dso_loader_t *loader; mtev_conf_section_t *include_sections = NULL; int section_cnt; if(!mtev_conf_get_stringbuf(sections[i], "ancestor-or-self::node()/@name", loader_name, sizeof(loader_name))) { mtevL(mtev_stderr, "No name defined in loader stanza %d\n", i+1); continue; } if(mtev_conf_env_off(sections[i], NULL)) { mtevL(mtev_debug, "loader %s environmentally disabled.\n", loader_name); continue; } loader = (mtev_dso_loader_t *) mtev_load_loader_image(&__mtev_image_loader, loader_name, sections[i]); if(!loader) { mtevL(mtev_stderr, "Failed to load loader %s\n", loader_name); mtev_dso_load_failure_count++; continue; } if(loader->config) { int rv; mtev_hash_table *config; include_sections = mtev_conf_get_sections(sections[i], "include", §ion_cnt); if ((include_sections) && (section_cnt == 1)) { config = mtev_conf_get_hash(*include_sections, "config"); } else { config = mtev_conf_get_hash(sections[i], "config"); } mtev_conf_release_sections(include_sections, section_cnt); rv = loader->config(loader, config); if(rv == 0) { mtev_hash_destroy(config, free, free); free(config); } else if(rv < 0) { mtevL(mtev_stderr, "Failed to config loader %s\n", loader_name); mtev_dso_load_failure_count++; continue; } } if(loader->init && loader->init(loader)) mtevL(mtev_stderr, "Failed to init loader %s\n", loader_name); } mtev_conf_release_sections(sections, cnt); }
static int stratcon_datastore_journal_sync(eventer_t e, int mask, void *closure, struct timeval *now) { mtev_hash_iter iter = MTEV_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; mtevL(ds_deb, "Syncing journal sets...\n"); if (syncset->ws) { while(mtev_hash_next(syncset->ws, &iter, &k, &klen, &vij)) { char tmppath[PATH_MAX], id_str[32]; int suffix_idx; ij = vij; mtevL(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: mtevL(noit_error, "rename failed(%s): (%s->%s)\n", strerror(errno), tmppath, ij->filename); exit(-1); } } if(ij->fd >= 0) { 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, mtev_false); } mtev_hash_destroy(syncset->ws, free, interim_journal_free); free(syncset->ws); } else { mtevL(noit_error, "attempted to sync non-existing working set\n"); } return 0; }
static int noit_console_show_check(mtev_console_closure_t ncct, int argc, char **argv, mtev_console_state_t *state, void *closure) { int i, cnt; mtev_conf_t_userdata_t *info; char xpath[1024]; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; mtev_conf_xml_xpath(NULL, &xpath_ctxt); if(argc > 1) { nc_printf(ncct, "requires zero or one arguments\n"); return -1; } info = mtev_console_userdata_get(ncct, MTEV_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++) { mtev_hash_iter iter = MTEV_HASH_ITER_ZERO; const char *k; int klen; void *data; uuid_t checkid; noit_check_t *check; mtev_hash_table *config; xmlNodePtr node, anode, mnode = NULL; char *uuid_conf; char *module, *value; node = (mtev_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); xmlFree(uuid_conf); #define MYATTR(a,n,b) _mtev_conf_get_string(node, &(n), "@" #a, &(b)) #define INHERIT(a,n,b) \ _mtev_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); \ if(value != NULL) free(value); \ } while(0) if(!INHERIT(module, mnode, module)) module = NULL; if(MYATTR(name, anode, value)) { nc_printf(ncct, " name: %s\n", value); free(value); } else nc_printf(ncct, " name: %s [from module]\n", module ? module : "[undef]"); nc_attr_show(ncct, "module", node, mnode, module); if(module) free(module); SHOW_ATTR(target); SHOW_ATTR(seq); SHOW_ATTR(resolve_rtype); SHOW_ATTR(period); SHOW_ATTR(timeout); SHOW_ATTR(oncheck); SHOW_ATTR(filterset); SHOW_ATTR(disable); /* Print out all the config settings */ config = mtev_conf_get_hash(node, "config"); while(mtev_hash_next(config, &iter, &k, &klen, &data)) { nc_printf(ncct, " config::%s: %s\n", k, (const char *)data); } mtev_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; stats_t *c; struct timeval *whence; mtev_hash_table *metrics; nc_printf(ncct, " target_ip: %s\n", check->target_ip); nc_printf(ncct, " currently: %08x ", check->flags); if(NOIT_CHECK_RUNNING(check)) { nc_printf(ncct, "running"); 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->fire_event != NULL) { struct timeval now, diff; mtev_gettimeofday(&now, NULL); sub_timeval(check->fire_event->whence, now, &diff); nc_printf(ncct, " next run: %0.3f seconds\n", diff.tv_sec + (diff.tv_usec / 1000000.0)); } else { nc_printf(ncct, " next run: unscheduled\n"); } c = noit_check_get_stats_current(check); whence = noit_check_stats_whence(c, NULL); if(whence->tv_sec == 0) { nc_printf(ncct, " last run: never\n"); } else { const char *status; struct timeval now, *then, diff; mtev_gettimeofday(&now, NULL); then = noit_check_stats_whence(c, NULL); sub_timeval(now, *then, &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(noit_check_stats_available(c, NULL)), noit_check_state_string(noit_check_stats_state(c, NULL))); status = noit_check_stats_status(c, NULL); nc_printf(ncct, " status: %s\n", status); nc_printf(ncct, " feeds: %d\n", check->feeds ? check->feeds->size : 0); } c = noit_check_get_stats_inprogress(check); metrics = noit_check_stats_metrics(c); if(mtev_hash_size(metrics) > 0) { nc_printf(ncct, " metrics (inprogress):\n"); nc_print_stat_metrics(ncct, check, c); } c = noit_check_get_stats_current(check); metrics = noit_check_stats_metrics(c); if(mtev_hash_size(metrics)) { nc_printf(ncct, " metrics (current):\n"); nc_print_stat_metrics(ncct, check, c); } c = noit_check_get_stats_previous(check); metrics = noit_check_stats_metrics(c); if(mtev_hash_size(metrics) > 0) { nc_printf(ncct, " metrics (previous):\n"); nc_print_stat_metrics(ncct, check, c); } } } out: if(pobj) xmlXPathFreeObject(pobj); return 0; }
static int mysql_drive_session(eventer_t e, int mask, void *closure, struct timeval *now) { const char *dsn, *sql; char sql_buff[8192]; char dsn_buff[512]; mysql_check_info_t *ci = closure; noit_check_t *check = ci->check; struct timeval t1, t2, diff; mtev_hash_table dsn_h = MTEV_HASH_EMPTY; const char *host=NULL; const char *user=NULL; const char *password=NULL; const char *dbname=NULL; const char *port_s=NULL; const char *socket=NULL; const char *sslmode=NULL; u_int32_t port; unsigned long client_flag = CLIENT_IGNORE_SIGPIPE; unsigned int timeout; if(mask & (EVENTER_READ | EVENTER_WRITE)) { /* this case is impossible from the eventer. It is called as * such on the synchronous completion of the event. */ mysql_log_results(ci->self, ci->check); mysql_cleanup(ci->self, ci->check); check->flags &= ~NP_RUNNING; return 0; } switch(mask) { case EVENTER_ASYNCH_WORK: ci->connect_duration = NULL; ci->query_duration = NULL; FETCH_CONFIG_OR(dsn, ""); noit_check_interpolate(dsn_buff, sizeof(dsn_buff), dsn, &ci->attrs, check->config); mysql_parse_dsn(dsn_buff, &dsn_h); mtev_hash_retrieve(&dsn_h, "host", strlen("host"), (void**)&host); mtev_hash_retrieve(&dsn_h, "user", strlen("user"), (void**)&user); mtev_hash_retrieve(&dsn_h, "password", strlen("password"), (void**)&password); mtev_hash_retrieve(&dsn_h, "dbname", strlen("dbname"), (void**)&dbname); mtev_hash_retrieve(&dsn_h, "port", strlen("port"), (void**)&port_s); if(mtev_hash_retrieve(&dsn_h, "sslmode", strlen("sslmode"), (void**)&sslmode) && !strcmp(sslmode, "require")) client_flag |= CLIENT_SSL; port = port_s ? strtol(port_s, NULL, 10) : 3306; mtev_hash_retrieve(&dsn_h, "socket", strlen("socket"), (void**)&socket); ci->conn = mysql_init(NULL); /* allocate us a handle */ if(!ci->conn) AVAIL_BAIL("mysql_init failed"); timeout = check->timeout / 1000; mysql_options(ci->conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&timeout); if(!mysql_real_connect(ci->conn, host, user, password, dbname, port, socket, client_flag)) { mtevL(noit_stderr, "error during mysql_real_connect: %s\n", mysql_error(ci->conn)); AVAIL_BAIL(mysql_error(ci->conn)); } if(mysql_ping(ci->conn)) AVAIL_BAIL(mysql_error(ci->conn)); #if MYSQL_VERSION_ID >= 50000 if (sslmode && !strcmp(sslmode, "require")) { /* mysql has a bad habit of silently failing to establish ssl and * falling back to unencrypted, so after making the connection, let's * check that we're actually using SSL by checking for a non-NULL * return value from mysql_get_ssl_cipher(). */ if (mysql_get_ssl_cipher(ci->conn) == NULL) { mtevL(nldeb, "mysql_get_ssl_cipher() returns NULL, but SSL mode required."); AVAIL_BAIL("mysql_get_ssl_cipher() returns NULL, but SSL mode required."); } } #endif gettimeofday(&t1, NULL); sub_timeval(t1, check->last_fire_time, &diff); ci->connect_duration_d = diff.tv_sec * 1000.0 + diff.tv_usec / 1000.0; ci->connect_duration = &ci->connect_duration_d; FETCH_CONFIG_OR(sql, ""); noit_check_interpolate(sql_buff, sizeof(sql_buff), sql, &ci->attrs, check->config); if (mysql_query(ci->conn, sql_buff)) AVAIL_BAIL(mysql_error(ci->conn)); gettimeofday(&t2, NULL); sub_timeval(t2, t1, &diff); ci->query_duration_d = diff.tv_sec * 1000.0 + diff.tv_usec / 1000.0; ci->query_duration = &ci->query_duration_d; ci->result = mysql_store_result(ci->conn); if(!ci->result) AVAIL_BAIL("mysql_store_result failed"); ci->rv = mysql_num_rows(ci->result); mysql_ingest_stats(ci); if(ci->result) { MYSQL_RES *result_swap = ci->result; ci->result = NULL; mysql_free_result(result_swap); } if(ci->conn) { MYSQL *conn_swap = ci->conn; ci->conn = NULL; mysql_close(conn_swap); } ci->timed_out = 0; mtev_hash_destroy(&dsn_h, free, free); return 0; break; case EVENTER_ASYNCH_CLEANUP: /* This sets us up for a completion call. */ e->mask = EVENTER_READ | EVENTER_WRITE; break; default: abort(); } return 0; }
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 = NULL; noit_check_t *c = NULL; xmlNodePtr a, co; mtev_hash_table *conf_hash = NULL; mtev_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); } if(!noit_check_validate_target(target)) { *error = "malformed target"; goto error; } if(!noit_check_validate_name(name)) { *error = "malformed name"; goto error; } if(module) 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 : ""); mtev_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; mtev_conf_section_t checks; name = noit_check_registered_module(i); checks = mtev_conf_get_section(NULL, "/noit/checks"); if(name) moptions[i] = mtev_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 = mtev_memory_safe_calloc(1, sizeof(*c)); c->module = strdup(module); c->flags = NP_TRANSIENT; noit_check_update(c, target, name, filterset, conf_hash, moptions, 0, timeout, NULL, 0, flags); 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) { mtev_hash_destroy(conf_hash, free, free); free(conf_hash); } if(moptions) { for(i=0; i<mod_cnt; i++) { if(moptions[i]) { mtev_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_filtersets_cull_unused() { mtev_hash_table active = MTEV_HASH_EMPTY; char *buffer = NULL; mtev_conf_section_t *declares; int i, n_uses = 0, n_declares = 0, removed = 0; const char *declare_xpath = "//filterset[@name and not (@cull='false')]"; declares = mtev_conf_get_sections(NULL, declare_xpath, &n_declares); if(declares) { /* store all unit filtersets used */ for(i=0;i<n_declares;i++) { if(!buffer) buffer = malloc(128); if(mtev_conf_get_stringbuf(declares[i], "@name", buffer, 128)) { if(mtev_hash_store(&active, buffer, strlen(buffer), declares[i])) { buffer = NULL; } else { void *vnode = NULL; /* We've just hit a duplicate.... check to see if there's an existing * entry and if there is, load the latest one and delete the old * one. */ mtev_hash_retrieve(&active, buffer, strlen(buffer), &vnode); if (vnode) { noit_filter_compile_add(declares[i]); CONF_REMOVE(vnode); xmlUnlinkNode(vnode); xmlFreeNode(vnode); removed++; if(mtev_hash_replace(&active, buffer, strlen(buffer), declares[i], free, NULL)) { buffer = NULL; } } } } } if(buffer) free(buffer); free(declares); } n_uses = noit_poller_do(filterset_accum, &active); if(n_uses > 0 && mtev_hash_size(&active) > 0) { mtev_hash_iter iter = MTEV_HASH_ITER_ZERO; const char *filter_name; int filter_name_len; void *vnode; while(mtev_hash_next(&active, &iter, &filter_name, &filter_name_len, &vnode)) { if(noit_filter_remove(vnode)) { CONF_REMOVE(vnode); xmlUnlinkNode(vnode); xmlFreeNode(vnode); removed++; } } } mtev_hash_destroy(&active, free, NULL); return removed; }
static int noit_console_config_show(mtev_console_closure_t ncct, int argc, char **argv, mtev_console_state_t *state, void *closure) { mtev_hash_iter iter = MTEV_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]; mtev_conf_t_userdata_t *info = NULL; mtev_hash_table *config; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL, current_ctxt; xmlDocPtr master_config = NULL; xmlNodePtr node = NULL; mtev_conf_xml_xpath(&master_config, &xpath_ctxt); if(argc > 1) { nc_printf(ncct, "too many arguments\n"); return -1; } info = mtev_console_userdata_get(ncct, MTEV_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 = (mtev_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); if(!strcmp((char *)node->name, "check")) continue; if(node->children && node->children == xmlGetLastChild(node) && xmlNodeIsText(node->children)) { char *node_str, *xmlpath; node_str = (char *)xmlXPathCastNodeToString(node->children); xmlpath = (char *)xmlGetNodePath(node); if(!titled++) nc_printf(ncct, "== Section Settings ==\n"); nc_printf(ncct, "%s: %s\n", xmlpath + cliplen, node_str); free(xmlpath); free(node_str); } } 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 = (mtev_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); titled = 0; config = mtev_conf_get_hash(node, "config"); while(mtev_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); } mtev_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++) { char *xmlpath; node = (mtev_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); if(!strcmp((char *)node->name, "check")) continue; if(!strcmp((char *)node->name, "filterset")) continue; xmlpath = (char *)xmlGetNodePath(node); if(strcmp(xmlpath + cliplen, "config")) { if(!(node->children && node->children == xmlGetLastChild(node) && xmlNodeIsText(node->children))) { if(!titled++) nc_printf(ncct, "== Subsections ==\n"); nc_printf(ncct, "%s\n", xmlpath + cliplen); } } free(xmlpath); } titled = 0; for(i=0; i<cnt; i++) { node = (mtev_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 = NULL; uuid_t checkid; 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); break; } } nc_printf(ncct, "check[@uuid=\"%s\"] ", uuid_str ? uuid_str : "undefined"); if(uuid_str && 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); } } if(uuid_str) free(uuid_str); 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 void free_hash_o_histotier(void *vh) { mtev_hash_table *h = vh; mtev_hash_destroy(h, free, free_histotier); free(h); }