Exemplo n.º 1
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;
}
Exemplo n.º 2
0
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);
    }
  }
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
int
noit_filter_exists(const char *name) {
  int exists;
  void *v;
  LOCKFS();
  exists = mtev_hash_retrieve(filtersets, name, strlen(name), &v);
  UNLOCKFS();
  return exists;
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
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;
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
0
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;
}
Exemplo n.º 17
0
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;
}
Exemplo n.º 18
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;
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
0
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);
  }
}
Exemplo n.º 22
0
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);
        }
      }
    }
  }
}
Exemplo n.º 23
0
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;
}
Exemplo n.º 24
0
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;
}
Exemplo n.º 25
0
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;
}
Exemplo n.º 26
0
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;
}
Exemplo n.º 27
0
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;
}
Exemplo n.º 28
0
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;
}
Exemplo n.º 29
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;
}
Exemplo n.º 30
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;
}