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 void distribute_metric(noit_metric_message_t *message) { void *vhash, *vinterests; char uuid_str[UUID_STR_LEN + 1]; uuid_unparse_lower(message->id.id, uuid_str); if(mtev_hash_retrieve(&id_level, (const char *) &message->id.id, UUID_SIZE, &vhash)) { if(mtev_hash_retrieve((mtev_hash_table *) vhash, message->id.name, message->id.name_len, &vinterests)) { caql_cnt_t *interests = vinterests; distribute_message_with_interests(interests, message); } } }
static int noit_config_check_update_attrs(xmlNodePtr node, int argc, char **argv) { int i, error = 0; if(argc % 2) return -1; for(i=0; i<argc; i+=2) { void *vattrinfo; struct _valid_attr_t *attrinfo; char *attr = argv[i], *val = NULL; if(!strcasecmp(argv[i], "no")) attr = argv[i+1]; else val = argv[i+1]; if(!mtev_hash_retrieve(&check_attrs, attr, strlen(attr), &vattrinfo)) { error = 1; break; } attrinfo = vattrinfo; /* The fixation stuff doesn't matter here, this check is brand-new */ xmlUnsetProp(node, (xmlChar *)attrinfo->name); if(val) xmlSetProp(node, (xmlChar *)attrinfo->name, (xmlChar *)val); CONF_DIRTY(node); mtev_conf_mark_changed(); } return error; }
mtev_dso_generic_t *mtev_dso_generic_lookup(const char *name) { void *vmodule; if(mtev_hash_retrieve(&generics, name, strlen(name), &vmodule)) return (mtev_dso_generic_t *)vmodule; return NULL; }
mtev_dso_loader_t * mtev_loader_lookup(const char *name) { void *vloader; if(mtev_hash_retrieve(&loaders, name, strlen(name), &vloader)) return (mtev_dso_loader_t *)vloader; return NULL; }
static int example_initiate(noit_module_t *self, noit_check_t *check, noit_check_t *cause) { struct example_check_info *ci = check->closure; const char *limit = "0"; struct timeval now, diff; BAIL_ON_RUNNING_CHECK(check); check->flags |= NP_RUNNING; mtev_hash_retrieve(check->config, "limit", strlen("limit"), (void **)&limit); ci->limit = atoi(limit); mtev_gettimeofday(&now, NULL); sub_timeval(now, check->last_fire_time, &diff); noit_stats_set_whence(check, &now); noit_stats_set_duration(check, diff.tv_sec * 1000 + diff.tv_usec / 1000); noit_stats_set_available(check, NP_AVAILABLE); noit_stats_set_status(check, "hello world"); if(ci->limit) { int value = (int)(lrand48() % ci->limit); noit_stats_set_metric(check, "random", METRIC_INT32, &value); noit_stats_set_state(check, NP_GOOD); } else { noit_stats_set_metric(check, "random", METRIC_INT32, NULL); noit_stats_set_state(check, NP_BAD); } noit_check_set_stats(check); check->flags &= ~NP_RUNNING; return 0; }
int noit_check_resolver_fetch(const char *target, char *buff, int len, uint8_t prefer_family) { int i, rv; uint8_t progression[2]; dns_cache_node *n; void *vnode; buff[0] = '\0'; if(!target) return -1; progression[0] = prefer_family; progression[1] = (prefer_family == AF_INET) ? AF_INET6 : AF_INET; if(mtev_hash_retrieve(&etc_hosts_cache, target, strlen(target), &vnode)) { static_host_node *node = vnode; for(i=0; i<2; i++) { switch(progression[i]) { case AF_INET: if(node->has_ip4) { inet_ntop(AF_INET, &node->ip4, buff, len); return 1; } break; case AF_INET6: if(node->has_ip6) { inet_ntop(AF_INET6, &node->ip6, buff, len); return 1; } break; } } } rv = -1; DCLOCK(); n = mtev_skiplist_find(&nc_dns_cache, target, NULL); if(n != NULL) { if(n->last_updated == 0) goto leave; /* not resolved yet */ rv = n->ip4_cnt + n->ip6_cnt; for(i=0; i<2; i++) { switch(progression[i]) { case AF_INET: if(n->ip4_cnt > 0) { inet_ntop(AF_INET, &n->ip4[0], buff, len); goto leave; } break; case AF_INET6: if(n->ip6_cnt > 0) { inet_ntop(AF_INET6, &n->ip6[0], buff, len); goto leave; } break; } } } leave: DCUNLOCK(); return rv; }
void noit_adjust_metric_interest(uuid_t id, const char *metric, short cnt) { int thread_id, icnt; void *vhash, *vinterests; mtev_hash_table *level2; caql_cnt_t *interests; thread_id = get_my_lane(); /* Get us our UUID->HASH(METRICS) mapping */ if(!mtev_hash_retrieve(&id_level, (const char *)id, UUID_SIZE, &vhash)) { int found; uuid_t *copy = malloc(UUID_SIZE); level2 = calloc(1,sizeof(*level2)); mtev_hash_init_locks(level2, MTEV_HASH_DEFAULT_SIZE, MTEV_HASH_LOCK_MODE_MUTEX); uuid_copy(*copy, id); if(!mtev_hash_store(&id_level, (const char *)copy, UUID_SIZE, level2)) { free(copy); free(level2); } found = mtev_hash_retrieve(&id_level, (const char *)id, UUID_SIZE, &vhash); mtevAssert(found); } level2 = vhash; if(!mtev_hash_retrieve(level2, metric, strlen(metric), &vinterests)) { int found; char *metric_copy; metric_copy = strdup(metric); vinterests = calloc(nthreads, sizeof(*interests)); if(!mtev_hash_store(level2, metric_copy, strlen(metric_copy), vinterests)) { free(metric_copy); free(vinterests); } found = mtev_hash_retrieve(level2, metric, strlen(metric), &vinterests); mtevAssert(found); } interests = vinterests; /* This is fine because thread_id is only ours */ icnt = interests[thread_id]; icnt += cnt; if(icnt < 0) icnt = 0; mtevAssert(icnt <= 0xffff); interests[thread_id] = icnt; }
int noit_filter_exists(const char *name) { int exists; void *v; LOCKFS(); exists = mtev_hash_retrieve(filtersets, name, strlen(name), &v); UNLOCKFS(); return exists; }
int mtev_hash_retr_str(mtev_hash_table *h, const char *k, int klen, const char **dstr) { void *data; if(!h) return 0; if(mtev_hash_retrieve(h, k, klen, &data)) { if(dstr) *dstr = data; return 1; } return 0; }
jlog_feed_stats_t * noit_jlog_feed_stats(const char *sub) { void *vs = NULL; jlog_feed_stats_t *s = NULL; if(mtev_hash_retrieve(&feed_stats, sub, strlen(sub), &vs)) return (jlog_feed_stats_t *)vs; s = calloc(1, sizeof(*s)); s->feed_name = strdup(sub); mtev_hash_store(&feed_stats, s->feed_name, strlen(s->feed_name), s); return s; }
static mtev_boolean noit_apply_filterrule(mtev_hash_table *m, pcre *p, pcre_extra *pe, const char *subj) { int rc, ovector[30]; if(m) { void *vptr; return mtev_hash_retrieve(m, subj, strlen(subj), &vptr); } if(!p) return mtev_true; rc = pcre_exec(p, pe, subj, strlen(subj), 0, 0, ovector, 30); if(rc >= 0) return mtev_true; return mtev_false; }
static mtev_hook_return_t histogram_hook_special_impl(void *closure, noit_check_t *check, stats_t *stats, const char *metric_name, metric_type_t type, const char *v, mtev_boolean success) { void *vht; histotier *ht; mtev_hash_table *config, *metrics; const char *track = ""; mtev_dso_generic_t *self = closure; struct histogram_config *conf = mtev_image_get_userdata(&self->hdr); if(success) return MTEV_HOOK_CONTINUE; config = noit_check_get_module_config(check, histogram_module_id); if(!config || mtev_hash_size(config) == 0) return MTEV_HOOK_CONTINUE; mtev_hash_retr_str(config, metric_name, strlen(metric_name), &track); if(!track || strcmp(track, "add")) return MTEV_HOOK_CONTINUE; metrics = noit_check_get_module_metadata(check, histogram_module_id); if(!metrics) { metrics = calloc(1, sizeof(*metrics)); noit_check_set_module_metadata(check, histogram_module_id, metrics, free_hash_o_histotier); } if(!mtev_hash_retrieve(metrics, metric_name, strlen(metric_name), &vht)) { ht = calloc(1, sizeof(*ht)); vht = ht; mtev_hash_store(metrics, strdup(metric_name), strlen(metric_name), vht); } else ht = vht; if(v != NULL) { /* We expect: H[<float>]=%d */ const char *lhs; char *endptr; double bucket; u_int64_t cnt; if(v[0] != 'H' || v[1] != '[') return MTEV_HOOK_CONTINUE; if(NULL == (lhs = strchr(v+2, ']'))) return MTEV_HOOK_CONTINUE; lhs++; if(*lhs++ != '=') return MTEV_HOOK_CONTINUE; bucket = strtod(v+2, &endptr); if(endptr == v+2) return MTEV_HOOK_CONTINUE; cnt = strtoull(lhs, &endptr, 10); if(endptr == lhs) return MTEV_HOOK_CONTINUE; update_histotier(ht, time(NULL), conf, check, metric_name, bucket, cnt); } return MTEV_HOOK_CONTINUE; }
static mtev_hash_table * stratcon_datastore_journal_remove(struct sockaddr *remote, const char *remote_cn) { void *vhash = NULL; if(mtev_hash_retrieve(&working_sets, remote_cn, strlen(remote_cn), &vhash)) { /* pluck it out */ mtev_hash_delete(&working_sets, remote_cn, strlen(remote_cn), free, NULL); } else { mtevL(noit_error, "attempted checkpoint on non-existing workingset: '%s'\n", remote_cn); } return vhash; }
static ssl_ctx_cache_node * ssl_ctx_cache_get(const char *key) { void *vnode; ssl_ctx_cache_node *node = NULL; mtev_atomic32_t newval; pthread_mutex_lock(&ssl_ctx_cache_lock); if(mtev_hash_retrieve(&ssl_ctx_cache, key, strlen(key), &vnode)) { node = vnode; newval = mtev_atomic_inc32(&node->refcnt); } pthread_mutex_unlock(&ssl_ctx_cache_lock); if(node) mtevL(eventer_deb, "ssl_ctx_cache->get(%p -> %d)\n", node, newval); return node; }
static mtev_hook_return_t histogram_hook_impl(void *closure, noit_check_t *check, stats_t *stats, metric_t *m) { void *vht; histotier *ht; mtev_hash_table *config, *metrics; const char *track = ""; mtev_dso_generic_t *self = closure; struct histogram_config *conf = mtev_image_get_userdata(&self->hdr); config = noit_check_get_module_config(check, histogram_module_id); if(!config || mtev_hash_size(config) == 0) return MTEV_HOOK_CONTINUE; mtev_hash_retr_str(config, m->metric_name, strlen(m->metric_name), &track); if(!track || strcmp(track, "add")) return MTEV_HOOK_CONTINUE; metrics = noit_check_get_module_metadata(check, histogram_module_id); if(!metrics) { metrics = calloc(1, sizeof(*metrics)); noit_check_set_module_metadata(check, histogram_module_id, metrics, free_hash_o_histotier); } if(!mtev_hash_retrieve(metrics, m->metric_name, strlen(m->metric_name), &vht)) { ht = calloc(1, sizeof(*ht)); vht = ht; mtev_hash_store(metrics, strdup(m->metric_name), strlen(m->metric_name), vht); } else ht = vht; if(m->metric_value.vp != NULL) { #define UPDATE_HISTOTIER(a) update_histotier(ht, time(NULL), conf, check, m->metric_name, *m->metric_value.a, 1) switch(m->metric_type) { case METRIC_UINT64: UPDATE_HISTOTIER(L); break; case METRIC_INT64: UPDATE_HISTOTIER(l); break; case METRIC_UINT32: UPDATE_HISTOTIER(I); break; case METRIC_INT32: UPDATE_HISTOTIER(i); break; case METRIC_DOUBLE: UPDATE_HISTOTIER(n); break; default: /*noop*/ break; } } return MTEV_HOOK_CONTINUE; }
int noit_check_etc_hosts_cache_refresh(eventer_t e, int mask, void *closure, struct timeval *now) { static struct stat last_stat; struct stat sb; struct hostent *ent; int reload = 0; memset(&sb, 0, sizeof(sb)); stat("/etc/hosts", &sb); #define CSTAT(f) (sb.f == last_stat.f) reload = ! (CSTAT(st_dev) && CSTAT(st_ino) && CSTAT(st_mode) && CSTAT(st_uid) && CSTAT(st_gid) && CSTAT(st_size) && CSTAT(st_mtime)); memcpy(&last_stat, &sb, sizeof(sb)); if(reload) { mtev_hash_delete_all(&etc_hosts_cache, free, free); while(NULL != (ent = gethostent())) { int i = 0; char *name = ent->h_name; while(name) { void *vnode; static_host_node *node; if(!mtev_hash_retrieve(&etc_hosts_cache, name, strlen(name), &vnode)) { vnode = node = calloc(1, sizeof(*node)); node->target = strdup(name); mtev_hash_store(&etc_hosts_cache, node->target, strlen(node->target), node); } node = vnode; if(ent->h_addrtype == AF_INET) { node->has_ip4 = 1; memcpy(&node->ip4, ent->h_addr_list[0], ent->h_length); } if(ent->h_addrtype == AF_INET6) { node->has_ip6 = 1; memcpy(&node->ip6, ent->h_addr_list[0], ent->h_length); } name = ent->h_aliases[i++]; } } endhostent(); mtevL(noit_debug, "reloaded %d /etc/hosts targets\n", mtev_hash_size(&etc_hosts_cache)); } eventer_add_in_s_us(noit_check_etc_hosts_cache_refresh, NULL, 1, 0); return 0; }
static mtev_boolean cross_module_reverse_allowed(noit_check_t *check, const char *secret) { void *vstr; mtev_hash_table *config; static int reverse_check_module_id = -1; if(reverse_check_module_id < 0) { reverse_check_module_id = noit_check_registered_module_by_name("reverse"); if(reverse_check_module_id < 0) return mtev_false; } config = noit_check_get_module_config(check, reverse_check_module_id); if(!config) return mtev_false; if(mtev_hash_retrieve(config, "key", strlen("key"), &vstr)) { if(!strcmp((const char *)vstr, secret)) return mtev_true; } return mtev_false; }
static ssl_ctx_cache_node * ssl_ctx_cache_set(ssl_ctx_cache_node *node) { void *vnode; mtev_atomic32_t newval; pthread_mutex_lock(&ssl_ctx_cache_lock); if(mtev_hash_retrieve(&ssl_ctx_cache, node->key, strlen(node->key), &vnode)) { node = vnode; } else { mtev_hash_store(&ssl_ctx_cache, node->key, strlen(node->key), node); } newval = mtev_atomic_inc32(&node->refcnt); pthread_mutex_unlock(&ssl_ctx_cache_lock); mtevL(eventer_deb, "ssl_ctx_cache->set(%p -> %d)\n", node, newval); return node; }
const char *eventer_name_for_callback_e(eventer_func_t f, eventer_t e) { void *vcd; struct callback_details *cd; if(mtev_hash_retrieve(&__func_to_name, (char *)&f, sizeof(f), &vcd)) { cd = vcd; if(cd->functional_name && e) { char *buf; buf = pthread_getspecific(_tls_funcname_key); if(!buf) { buf = malloc(FUNCNAME_SIZE); pthread_setspecific(_tls_funcname_key, buf); } cd->functional_name(buf, FUNCNAME_SIZE, e, cd->closure); return buf; } return cd->simple_name; } return NULL; }
static void nc_print_stat_metrics(mtev_console_closure_t ncct, noit_check_t *check, stats_t *c) { int mcount=0, cnt=0; const char **sorted_keys; char buff[256]; mtev_boolean filtered; mtev_hash_table *metrics; mtev_hash_iter iter = MTEV_HASH_ITER_ZERO; const char *k; int klen; void *data; metrics = noit_check_stats_metrics(c); memset(&iter, 0, sizeof(iter)); while(mtev_hash_next(metrics, &iter, &k, &klen, &data)) cnt++; sorted_keys = malloc(cnt * sizeof(*sorted_keys)); memset(&iter, 0, sizeof(iter)); while(mtev_hash_next(metrics, &iter, &k, &klen, &data)) { if(sorted_keys && mcount < cnt) sorted_keys[mcount++] = k; else { 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); } } if(sorted_keys) { int j; qsort(sorted_keys, mcount, sizeof(*sorted_keys), _qsort_string_compare); for(j=0;j<mcount;j++) { if(mtev_hash_retrieve(metrics, sorted_keys[j], strlen(sorted_keys[j]), &data)) { 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); } } free(sorted_keys); } }
static void noit_fq_set_filters(mq_command_t *commands, int count) { int i, j; if (!global_fq_ctx.filtered_exchange[0]) { mtevL(mtev_error, "ERROR: trying to set check for filtered exchange when no such exchange exists\n"); return; } for (i=0; i<count; i++) { if (commands[i].action == MQ_ACTION_SET) { mtev_hash_table *metric_table = calloc(1, sizeof(mtev_hash_table)); mtev_hash_init(metric_table); for (j=0; j<commands[i].check.metric_count; j++) { mtev_hash_store(metric_table, strdup(commands[i].check.metrics[j]), strlen(commands[i].check.metrics[j]), NULL); filtered_metrics_exist = true; } mtev_hash_replace(&filtered_checks_hash, strdup(commands[i].check.uuid), strlen(commands[i].check.uuid), metric_table, free, noit_fq_free_metric_hash); } else { if (commands[i].check.metric_count == 0) { /* Forget the whole check */ if (!mtev_hash_delete(&filtered_checks_hash, commands[i].check.uuid, strlen(commands[i].check.uuid), free, noit_fq_free_metric_hash)) { mtevL(mtev_error, "failed forgetting check %s - check does not exist\n", commands[i].check.uuid); } } else { mtev_hash_table *filtered_metrics; if(mtev_hash_retrieve(&filtered_checks_hash, commands[i].check.uuid, strlen(commands[i].check.uuid), (void**)&filtered_metrics)) { for (j=0; j<commands[i].check.metric_count; j++) { if (!mtev_hash_delete(filtered_metrics, commands[i].check.metrics[j], strlen(commands[i].check.metrics[j]), free, noit_fq_free_metric_hash)) { mtevL(mtev_error, "failed forgetting metric '%s' for check %s - metric does not exist\n", commands[i].check.metrics[j], commands[i].check.uuid); } } } else { mtevL(mtev_error, "failed forgetting metrics for check %s - check does not exist\n", commands[i].check.uuid); } } } } }
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_filter_configure(mtev_console_closure_t ncct, int argc, char **argv, mtev_console_state_t *state, void *closure) { xmlNodePtr parent, fsnode = NULL; int rv = -1; mtev_conf_t_userdata_t *info; char xpath[1024]; info = mtev_console_userdata_get(ncct, MTEV_CONF_T_USERDATA); if(!info) { nc_printf(ncct, "internal error\n"); goto cleanup; } if(strncmp(info->path, "/filtersets/", strlen("/filtersets/")) && strcmp(info->path, "/filtersets")) { nc_printf(ncct, "filterset only allows inside /filtersets (not %s)\n", info->path); goto cleanup; } if(argc != 1) { nc_printf(ncct, "filterset requires one argument\n"); goto cleanup; } snprintf(xpath, sizeof(xpath), "/%s", info->path); parent = mtev_conf_get_section(NULL, xpath); if(!parent) { nc_printf(ncct, "internal error, can't final current working path\n"); goto cleanup; } snprintf(xpath, sizeof(xpath), "filterset[@name=\"%s\"]", argv[0]); fsnode = mtev_conf_get_section(parent, xpath); if(closure) { int removed; removed = noit_filter_remove(fsnode); nc_printf(ncct, "%sremoved filterset '%s'\n", removed ? "" : "failed to ", argv[0]); if(removed) { CONF_REMOVE(fsnode); xmlUnlinkNode(fsnode); xmlFreeNode(fsnode); } rv = !removed; goto cleanup; } if(!fsnode) { void *vfs; nc_printf(ncct, "Cannot find filterset '%s'\n", argv[0]); LOCKFS(); if(mtev_hash_retrieve(filtersets, argv[0], strlen(argv[0]), &vfs)) { UNLOCKFS(); nc_printf(ncct, "filter of the same name already exists\n"); goto cleanup; } UNLOCKFS(); /* Fine the parent path */ fsnode = xmlNewNode(NULL, (xmlChar *)"filterset"); xmlSetProp(fsnode, (xmlChar *)"name", (xmlChar *)argv[0]); xmlAddChild(parent, fsnode); nc_printf(ncct, "created new filterset\n"); } if(info) { char *xmlpath = NULL; free(info->path); xmlpath = (char *)xmlGetNodePath(fsnode); info->path = strdup(xmlpath + strlen("/noit")); free(xmlpath); strlcpy(info->filter_name, argv[0], sizeof(info->filter_name)); if(state) { mtev_console_state_push_state(ncct, state); mtev_console_state_init(ncct); } } cleanup: return rv; }
mtev_boolean noit_apply_filterset(const char *filterset, noit_check_t *check, metric_t *metric) { /* We pass in filterset here just in case someone wants to apply * a filterset other than check->filterset.. You never know. */ void *vfs; if(!filterset) return mtev_true; /* No filter */ if(!filtersets) return mtev_false; /* Couldn't possibly match */ LOCKFS(); if(mtev_hash_retrieve(filtersets, filterset, strlen(filterset), &vfs)) { filterset_t *fs = (filterset_t *)vfs; filterrule_t *r, *skipto_rule = NULL; int idx = 0; mtev_atomic_inc32(&fs->ref_cnt); UNLOCKFS(); #define MATCHES(rname, value) noit_apply_filterrule(r->rname##_ht, r->rname ? r->rname : r->rname##_override, r->rname ? r->rname##_e : NULL, value) for(r = fs->rules; r; r = r->next) { int need_target, need_module, need_name, need_metric; /* If we're targeting a skipto rule, match or continue */ idx++; if(skipto_rule && skipto_rule != r) continue; skipto_rule = NULL; need_target = !MATCHES(target, check->target); need_module = !MATCHES(module, check->module); need_name = !MATCHES(name, check->name); need_metric = !MATCHES(metric, metric->metric_name); if(!need_target && !need_module && !need_name && !need_metric) { if(r->type == NOIT_FILTER_SKIPTO) { skipto_rule = r->skipto_rule; continue; } return (r->type == NOIT_FILTER_ACCEPT) ? mtev_true : mtev_false; } /* If we need some of these and we have an auto setting that isn't fulfilled for each of them, we can add and succeed */ #define CHECK_ADD(rname) (!need_##rname || (r->rname##_auto_hash_max > 0 && r->rname##_ht && mtev_hash_size(r->rname##_ht) < r->rname##_auto_hash_max)) if(CHECK_ADD(target) && CHECK_ADD(module) && CHECK_ADD(name) && CHECK_ADD(metric)) { #define UPDATE_FILTER_RULE(rnum, rname, value) do { \ mtev_hash_replace(r->rname##_ht, strdup(value), strlen(value), NULL, free, NULL); \ if(noit_filter_update_conf_rule(fs->name, rnum, #rname, value) < 0) { \ mtevL(noit_error, "Error updating configuration for new filter auto_add on %s=%s\n", #rname, value); \ } \ } while(0) if(need_target) UPDATE_FILTER_RULE(idx, target, check->target); if(need_module) UPDATE_FILTER_RULE(idx, module, check->module); if(need_name) UPDATE_FILTER_RULE(idx, name, check->name); if(need_metric) UPDATE_FILTER_RULE(idx, metric, metric->metric_name); noit_filterset_log_auto_add(fs->name, check, metric, r->type == NOIT_FILTER_ACCEPT); if(r->type == NOIT_FILTER_SKIPTO) { skipto_rule = r->skipto_rule; continue; } return (r->type == NOIT_FILTER_ACCEPT) ? mtev_true : mtev_false; } } filterset_free(fs); return mtev_false; } UNLOCKFS(); return mtev_false; }
static interim_journal_t * interim_journal_get(struct sockaddr *remote, const char *remote_cn_in, int storagenode_id, const char *fqdn_in) { void *vhash, *vij; mtev_hash_table *working_set; interim_journal_t *ij; struct timeval now; char jpath[PATH_MAX]; char remote_str[128]; const char *remote_cn = remote_cn_in ? remote_cn_in : "default"; const char *fqdn = fqdn_in ? fqdn_in : "default"; mtev_convert_sockaddr_to_buff(remote_str, sizeof(remote_str), remote); if(!*remote_str) strlcpy(remote_str, "default", sizeof(remote_str)); /* Lookup the working set */ if(!mtev_hash_retrieve(&working_sets, remote_cn, strlen(remote_cn), &vhash)) { working_set = calloc(1, sizeof(*working_set)); mtev_hash_store(&working_sets, strdup(remote_cn), strlen(remote_cn), working_set); } else working_set = vhash; /* Lookup the interim journal within the working set */ if(!mtev_hash_retrieve(working_set, fqdn, strlen(fqdn), &vij)) { ij = calloc(1, sizeof(*ij)); gettimeofday(&now, NULL); snprintf(jpath, sizeof(jpath), "%s/%s/%s/%d/%08x%08x.tmp", basejpath, remote_str, remote_cn, storagenode_id, (unsigned int)now.tv_sec, (unsigned int)now.tv_usec); ij->remote_str = strdup(remote_str); ij->remote_cn = strdup(remote_cn); ij->fqdn = fqdn_in ? strdup(fqdn_in) : NULL; ij->storagenode_id = storagenode_id; ij->filename = strdup(jpath); ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640); if(ij->fd < 0 && errno == ENOENT) { if(mkdir_for_file(ij->filename, 0750)) { mtevL(noit_error, "Failed to create dir for '%s': %s\n", ij->filename, strerror(errno)); exit(-1); } ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640); } if(ij->fd < 0 && errno == EEXIST) { /* This can only occur if we crash after before checkpointing */ unlink(ij->filename); ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640); } if(ij->fd < 0) { mtevL(noit_error, "Failed to open interim journal '%s': %s\n", ij->filename, strerror(errno)); exit(-1); } mtev_hash_store(working_set, strdup(fqdn), strlen(fqdn), ij); } else ij = vij; return ij; }
static int ping_icmp_handler(eventer_t e, int mask, void *closure, struct timeval *now, u_int8_t family) { noit_module_t *self = (noit_module_t *)closure; ping_icmp_data_t *ping_data; struct check_info *data; char packet[1500]; int packet_len = sizeof(packet); union { struct sockaddr_in in4; struct sockaddr_in6 in6; } from; unsigned int from_len; struct ping_payload *payload; if(family != AF_INET && family != AF_INET6) return EVENTER_READ; ping_data = noit_module_get_userdata(self); while(1) { struct ping_session_key k; int inlen; u_int8_t iphlen = 0; void *vcheck; noit_check_t *check; struct timeval tt, whence; from_len = sizeof(from); inlen = recvfrom(e->fd, packet, packet_len, 0, (struct sockaddr *)&from, &from_len); mtev_gettimeofday(now, NULL); /* set it, as we care about accuracy */ if(inlen < 0) { if(errno == EAGAIN || errno == EINTR) break; mtevLT(nldeb, now, "ping_icmp recvfrom: %s\n", strerror(errno)); break; } if(family == AF_INET) { struct icmp *icp4; iphlen = ((struct ip *)packet)->ip_hl << 2; if((inlen-iphlen) != sizeof(struct icmp)+PING_PAYLOAD_LEN) { mtevLT(nldeb, now, "ping_icmp bad size: %d+%d\n", iphlen, inlen-iphlen); continue; } icp4 = (struct icmp *)(packet + iphlen); payload = (struct ping_payload *)(icp4 + 1); if(icp4->icmp_type != ICMP_ECHOREPLY) { mtevLT(nldeb, now, "ping_icmp bad type: %d\n", icp4->icmp_type); continue; } if(icp4->icmp_id != (((vpsized_uint)self) & 0xffff)) { mtevLT(nldeb, now, "ping_icmp not sent from this instance (%d:%d) vs. %lu\n", icp4->icmp_id, ntohs(icp4->icmp_seq), (unsigned long)(((vpsized_uint)self) & 0xffff)); continue; } } else if(family == AF_INET6) { struct icmp6_hdr *icp6 = (struct icmp6_hdr *)packet; if((inlen) != sizeof(struct icmp6_hdr)+PING_PAYLOAD_LEN) { mtevLT(nldeb, now, "ping_icmp bad size: %d+%d\n", iphlen, inlen-iphlen); continue; } payload = (struct ping_payload *)(icp6+1); if(icp6->icmp6_type != ICMP6_ECHO_REPLY) { mtevLT(nldeb, now, "ping_icmp bad type: %d\n", icp6->icmp6_type); continue; } if(icp6->icmp6_id != (((vpsized_uint)self) & 0xffff)) { mtevLT(nldeb, now, "ping_icmp not sent from this instance (%d:%d) vs. %lu\n", icp6->icmp6_id, ntohs(icp6->icmp6_seq), (unsigned long)(((vpsized_uint)self) & 0xffff)); continue; } } else { /* This should be unreachable */ continue; } check = NULL; k.addr_of_check = payload->addr_of_check; uuid_copy(k.checkid, payload->checkid); if(mtev_hash_retrieve(ping_data->in_flight, (const char *)&k, sizeof(k), &vcheck)) check = vcheck; /* make sure this check is from this generation! */ if(!check) { char uuid_str[37]; uuid_unparse_lower(payload->checkid, uuid_str); mtevLT(nldeb, now, "ping_icmp response for unknown check '%s'\n", uuid_str); continue; } if((check->generation & 0xffff) != payload->generation) { mtevLT(nldeb, now, "ping_icmp response in generation gap\n"); continue; } data = (struct check_info *)check->closure; /* If there is no timeout_event, the check must have completed. * We have nothing to do. */ if(!data->timeout_event) continue; /* Sanity check the payload */ if(payload->check_no != data->check_no) continue; if(payload->check_pack_cnt != data->expected_count) continue; if(payload->check_pack_no >= data->expected_count) continue; whence.tv_sec = payload->tv_sec; whence.tv_usec = payload->tv_usec; sub_timeval(*now, whence, &tt); data->turnaround[payload->check_pack_no] = (float)tt.tv_sec + (float)tt.tv_usec / 1000000.0; if(ping_icmp_is_complete(self, check)) { ping_icmp_log_results(self, check); eventer_remove(data->timeout_event); free(data->timeout_event->closure); eventer_free(data->timeout_event); data->timeout_event = NULL; check->flags &= ~NP_RUNNING; k.addr_of_check = (vpsized_uint)check ^ random_num; uuid_copy(k.checkid, check->checkid); mtev_hash_delete(ping_data->in_flight, (const char *)&k, sizeof(k), free, NULL); } } return EVENTER_READ; }
eventer_func_t eventer_callback_for_name(const char *name) { void *vf; if(mtev_hash_retrieve(&__name_to_func, name, strlen(name), &vf)) return (eventer_func_t)vf; return (eventer_func_t)NULL; }
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; }
static int noit_fq_submit(iep_thread_driver_t *dr, const char *payload, size_t payloadlen) { int i; struct fq_driver *driver = (struct fq_driver *)dr; const char *routingkey = driver->routingkey; mtev_hash_table *filtered_metrics; char uuid_formatted_str[UUID_STR_LEN+1]; bool is_bundle = false, is_metric = false, send = false; fq_msg *msg; char *metric = NULL; if(*payload == 'M' || *payload == 'S' || *payload == 'C' || (*payload == 'H' && payload[1] == '1') || (*payload == 'F' && payload[1] == '1') || (*payload == 'B' && (payload[1] == '1' || payload[1] == '2'))) { char uuid_str[32 * 2 + 1]; int account_id, check_id; if (*payload == 'B') is_bundle = true; else if ((*payload == 'H') || (*payload == 'M')) { is_metric = true; } if(extract_uuid_from_jlog(payload, payloadlen, &account_id, &check_id, uuid_str, uuid_formatted_str, &metric)) { if(*routingkey) { char *replace; int newlen = strlen(driver->routingkey) + 1 + sizeof(uuid_str) + 2 * 32; replace = alloca(newlen); snprintf(replace, newlen, "%s.%x.%x.%d.%d%s", driver->routingkey, account_id%16, (account_id/16)%16, account_id, check_id, uuid_str); routingkey = replace; } } } /* Let through any messages that aren't metrics or bundles */ if (!is_bundle && !is_metric) { send = true; } /* Setup our message */ msg = fq_msg_alloc(payload, payloadlen); if(msg == NULL) { driver->allocation_failures++; if (metric) free(metric); return -1; } driver->msg_cnt++; fq_msg_exchange(msg, driver->exchange, strlen(driver->exchange)); mtevL(mtev_debug, "route[%s] -> %s\n", driver->exchange, routingkey); fq_msg_route(msg, routingkey, strlen(routingkey)); fq_msg_id(msg, NULL); if (global_fq_ctx.round_robin) { int checked = 0, good = 0; time_t cur_time; while (1) { if (!global_fq_ctx.down_host[global_fq_ctx.round_robin_target]) { good = 1; break; } cur_time = time(NULL); if (cur_time - global_fq_ctx.last_error[global_fq_ctx.round_robin_target] >= 10) { global_fq_ctx.down_host[global_fq_ctx.round_robin_target] = false; good = 1; break; } global_fq_ctx.round_robin_target = (global_fq_ctx.round_robin_target+1) % driver->nhosts; checked++; if (checked == driver->nhosts) { /* This means everybody is down.... just try to send to whatever fq we're pointing at */ break; } } if (good) { if(fq_client_publish(driver->client[global_fq_ctx.round_robin_target], msg) == 1) { BUMPSTAT(global_fq_ctx.round_robin_target, publications); } else { BUMPSTAT(global_fq_ctx.round_robin_target, client_tx_drop); } } /* Go ahead and try to publish to the hosts that are down, just in case they've come back up. This should help minimize lost messages */ for (i=0; i<driver->nhosts; i++) { if (global_fq_ctx.down_host[i]) { if(fq_client_publish(driver->client[i], msg) == 1) { BUMPSTAT(i, publications); } else { BUMPSTAT(i, client_tx_drop); } } } global_fq_ctx.round_robin_target = (global_fq_ctx.round_robin_target+1) % driver->nhosts; } else { for(i=0; i<driver->nhosts; i++) { if(fq_client_publish(driver->client[i], msg) == 1) { BUMPSTAT(i, publications); } else { BUMPSTAT(i, client_tx_drop); } } } fq_msg_deref(msg); if (!send) { if(mtev_hash_retrieve(&filtered_checks_hash, uuid_formatted_str, strlen(uuid_formatted_str), (void**)&filtered_metrics)) { if (is_bundle || (is_metric && mtev_hash_size(filtered_metrics) == 0)) { send = true; } else if (is_metric) { void *tmp; if (mtev_hash_retrieve(filtered_metrics, metric, strlen(metric), &tmp)) { send = true; } } } } if (global_fq_ctx.filtered_exchange[0] && send) { fq_msg *msg2; msg2 = fq_msg_alloc(payload, payloadlen); fq_msg_exchange(msg2, driver->filtered_exchange, strlen(driver->filtered_exchange)); mtevL(mtev_debug, "route[%s] -> %s\n", driver->filtered_exchange, routingkey); fq_msg_route(msg2, routingkey, strlen(routingkey)); fq_msg_id(msg2, NULL); for(i=0; i<driver->nhosts; i++) { if(fq_client_publish(driver->client[i], msg2) == 1) { BUMPSTAT(i, publications); } else { BUMPSTAT(i, client_tx_drop); } } fq_msg_deref(msg2); } if (metric) free(metric); return 0; }