Пример #1
0
static int statsd_read(void) /* {{{ */
{
  c_avl_iterator_t *iter;
  char *name;
  statsd_metric_t *metric;

  char **to_be_deleted = NULL;
  size_t to_be_deleted_num = 0;

  pthread_mutex_lock(&metrics_lock);

  if (metrics_tree == NULL) {
    pthread_mutex_unlock(&metrics_lock);
    return 0;
  }

  iter = c_avl_get_iterator(metrics_tree);
  while (c_avl_iterator_next(iter, (void *)&name, (void *)&metric) == 0) {
    if ((metric->updates_num == 0) &&
        ((conf_delete_counters && (metric->type == STATSD_COUNTER)) ||
         (conf_delete_timers && (metric->type == STATSD_TIMER)) ||
         (conf_delete_gauges && (metric->type == STATSD_GAUGE)) ||
         (conf_delete_sets && (metric->type == STATSD_SET)))) {
      DEBUG("statsd plugin: Deleting metric \"%s\".", name);
      strarray_add(&to_be_deleted, &to_be_deleted_num, name);
      continue;
    }

    /* Names have a prefix, e.g. "c:", which determines the (statsd) type.
     * Remove this here. */
    statsd_metric_submit_unsafe(name + 2, metric);

    /* Reset the metric. */
    metric->updates_num = 0;
    if (metric->type == STATSD_SET)
      statsd_metric_clear_set_unsafe(metric);
  }
  c_avl_iterator_destroy(iter);

  for (size_t i = 0; i < to_be_deleted_num; i++) {
    int status;

    status = c_avl_remove(metrics_tree, to_be_deleted[i], (void *)&name,
                          (void *)&metric);
    if (status != 0) {
      ERROR("stats plugin: c_avl_remove (\"%s\") failed with status %i.",
            to_be_deleted[i], status);
      continue;
    }

    sfree(name);
    statsd_metric_free(metric);
  }

  pthread_mutex_unlock(&metrics_lock);

  strarray_free(to_be_deleted, to_be_deleted_num);

  return 0;
} /* }}} int statsd_read */
Пример #2
0
void uc_iterator_destroy (uc_iter_t *iter)
{
    if (iter == NULL)
        return;

    c_avl_iterator_destroy (iter->iter);
    pthread_mutex_unlock (&cache_lock);

    free (iter);
} /* void uc_iterator_destroy */
void instances_of_types_tree_print(void) {
	c_avl_iterator_t *iter;
	char *k;
	instances_list_t *v;
	int n=0;

	INFO(OUTPUT_PREFIX_STRING "INSTANCES");
	pthread_mutex_lock (&instances_of_types_mutex);
	iter = c_avl_get_iterator (instances_of_types_tree);
	while (c_avl_iterator_next (iter, (void *) &k, (void *) &v) == 0)
	{
		int i;
			INFO(OUTPUT_PREFIX_STRING "INSTANCES of %s", k);
		for(i=0; v->instance[i]; i++) {
			INFO(OUTPUT_PREFIX_STRING "INSTANCES :        %s", v->instance[i]);
		}
		n++;
	} /* while (c_avl_iterator_next) */
	c_avl_iterator_destroy (iter);
	pthread_mutex_unlock (&instances_of_types_mutex);
	INFO(OUTPUT_PREFIX_STRING "INSTANCES nb=%d",n);
}
static int
basic_aggregator_read_all_aggregators (void) {
		c_avl_iterator_t *iter;
		char *k;
		aggregator_definition_t *agg;
		int status;
		struct stat buf;
		short update_config = 1;

		/* Check if we should reread the configuration file */
		errno=0;
		if(-1 == stat(configuration_filename, &buf)) {
				ERROR (OUTPUT_PREFIX_STRING "Cannot stat configuration file '%s' (errno=%d)", configuration_filename,errno);
				return(-1);
		}
		if(buf.st_mtime > configuration_filename_date) {
				configuration_filename_date = buf.st_mtime;
		} else {
				update_config = 0;
		}

		/* Reread the configuration file if needed */
		if(1 == update_config) {
				status = basic_aggregator_read_config_file_and_update_aggregator_definitions(configuration_filename);
				if(status != 0) return -1;
		}

		/* Aggregate for all the aggregators */
		iter = c_avl_get_iterator (aggregator);
		while (c_avl_iterator_next (iter, (void *) &k, (void *) &agg) == 0)
		{
				basic_aggregator_read(agg);
		} /* while (c_avl_iterator_next) */
		c_avl_iterator_destroy (iter);

		return(0);
}
static int basic_aggregator_submit_resultvalue (
	const aggregator_definition_t *agg,
	c_avl_tree_t *ds_data
	)
{
	value_t *values;
	value_list_t vl = VALUE_LIST_INIT;
	const data_set_t *ds;
	char *identifier;
	char *hostname;
	char *plugin;
	char *plugin_instance;
	char *type;
	char *type_instance;
	int  status;
	int i;
	int submit_ok;
	aggregator_operation_e operation;
	c_avl_iterator_t *iter;
	char *key_instance;
	c_avl_tree_t *ds_tree;

	identifier = sstrdup (agg->resultvalue);

	status = parse_identifier (identifier, &hostname,
					&plugin, &plugin_instance,
					&type, &type_instance);
	if (status != 0)
	{
		ERROR (OUTPUT_PREFIX_STRING "Cannot parse value `%s'.", agg->resultvalue);
		sfree (identifier);
		return (-1);
	}

	if((NULL == type) || (type[0] == '\0')) {
		ERROR (OUTPUT_PREFIX_STRING "parse_identifier() : type == NULL or is empty (identifier='%s')", identifier);
		sfree (identifier);
		return (-1);
	}

	ds = plugin_get_ds (type);
	if (ds == NULL)
	{
		ERROR (OUTPUT_PREFIX_STRING "plugin_get_ds (%s) == NULL", type);
		sfree (identifier);
		return (-1);
	}
	
	if(NULL == (values = malloc(ds->ds_num* sizeof(*values)))) {
		ERROR (OUTPUT_PREFIX_STRING "Could not allocate memory");
		sfree (identifier);
		return (-1);
	}
	
	iter = c_avl_get_iterator (ds_data);
	while (c_avl_iterator_next (iter, (void *) &key_instance, (void *) &ds_tree) == 0) {
	
		for (operation=0; operation < nb_enum_in_aggregator_operation_e; operation++) {
			if(0 == agg->operation[operation]) continue;
			memset(values, '\0', ds->ds_num*sizeof(*values));
			submit_ok = 1;
			for(i=0; i<ds->ds_num; i++) {
				value_and_nb_t *v;
				if(0 == c_avl_get(ds_tree, ds->ds[i].name,(void*)&v)) {
					switch(operation) {
						case operation_SUM : values[i].gauge = v->val; break;
						case operation_AVG : values[i].gauge = v->val/v->nb; break;
						default : assert (11 == 12); /* this should never happen */
					}
				} else {
						submit_ok = 0;
				}
	
			}
			if(submit_ok) {
				int l = 0;
				int pos = 0;
	
				vl.values = values;
				vl.values_len = ds->ds_num;
				
				if(plugin_instance) {
					l = strlen(plugin_instance);
				}
				if(l) {
					sstrncpy (vl.plugin_instance, plugin_instance, l+1);
					pos += l;
					sstrncpy (vl.plugin_instance + pos, "_", DATA_MAX_NAME_LEN - pos);
					pos += 1;
				}
				switch(operation) {
						case operation_SUM : sstrncpy (vl.plugin_instance + pos, "sum", DATA_MAX_NAME_LEN - pos); break;
						case operation_AVG : sstrncpy (vl.plugin_instance + pos, "avg", DATA_MAX_NAME_LEN - pos); break;
						default : assert (11 == 12); /* this should never happen */
				}
	
				sstrncpy (vl.host, hostname, sizeof (vl.host));
				sstrncpy (vl.plugin, plugin, sizeof (vl.plugin));
				sstrncpy (vl.type, type, sizeof (vl.type));
				if(key_instance[0]) sstrncpy (vl.type_instance, key_instance, sizeof (vl.type_instance));
	
#ifdef DEBUG_THIS
INFO(OUTPUT_PREFIX_STRING "DEBUG : dispatch '%s/%s-%s/%s%s%s'", vl.host, vl.plugin, vl.plugin_instance, vl.type,
	                                                               (vl.type_instance && vl.type_instance[0])?"-":"",
																   vl.type_instance?vl.type_instance:"(null)");
#endif
#ifdef DEBUG_THIS
do {
	int i;
	if(strcmp(vl.host, "aggregator_2")) break;
	for(i=0; i<vl.values_len; i++) {
INFO(OUTPUT_PREFIX_STRING "DEBUG : dispatch '%s/%s-%s/%s%s%s DS '%s'=%12e", vl.host, vl.plugin, vl.plugin_instance, vl.type,
	                                                               (vl.type_instance && vl.type_instance[0])?"-":"",
																   vl.type_instance?vl.type_instance:"(null)",
																   ds->ds[i].name, values[i].gauge
																   );
	}
} while(0);
#endif
				plugin_dispatch_values (&vl);
			}
		}
	} /* while (c_avl_iterator_next) */
	c_avl_iterator_destroy (iter);
	sfree (identifier);
	return(0);
} /* void basic_aggregator_submit_resultvalue */
Пример #6
0
int uc_get_names (char ***ret_names, time_t **ret_times, size_t *ret_number)
{
  c_avl_iterator_t *iter;
  char *key;
  cache_entry_t *value;

  char **names = NULL;
  time_t *times = NULL;
  size_t number = 0;

  int status = 0;

  if ((ret_names == NULL) || (ret_number == NULL))
    return (-1);

  pthread_mutex_lock (&cache_lock);

  iter = c_avl_get_iterator (cache_tree);
  while (c_avl_iterator_next (iter, (void *) &key, (void *) &value) == 0)
  {
    char **temp;

    /* remove missing values when list values */
    if (value->state == STATE_MISSING)
      continue;

    if (ret_times != NULL)
    {
      time_t *tmp_times;

      tmp_times = (time_t *) realloc (times, sizeof (time_t) * (number + 1));
      if (tmp_times == NULL)
      {
	status = -1;
	break;
      }
      times = tmp_times;
      times[number] = value->last_time;
    }

    temp = (char **) realloc (names, sizeof (char *) * (number + 1));
    if (temp == NULL)
    {
      status = -1;
      break;
    }
    names = temp;
    names[number] = strdup (key);
    if (names[number] == NULL)
    {
      status = -1;
      break;
    }
    number++;
  } /* while (c_avl_iterator_next) */

  c_avl_iterator_destroy (iter);
  pthread_mutex_unlock (&cache_lock);

  if (status != 0)
  {
    size_t i;
    
    for (i = 0; i < number; i++)
    {
      sfree (names[i]);
    }
    sfree (names);

    return (-1);
  }

  *ret_names = names;
  if (ret_times != NULL)
    *ret_times = times;
  *ret_number = number;

  return (0);
} /* int uc_get_names */
Пример #7
0
int uc_check_timeout (void)
{
  time_t now;
  cache_entry_t *ce;

  char **keys = NULL;
  int keys_len = 0;

  char *key;
  c_avl_iterator_t *iter;
  int i;
  
  pthread_mutex_lock (&cache_lock);

  now = time (NULL);

  /* Build a list of entries to be flushed */
  iter = c_avl_get_iterator (cache_tree);
  while (c_avl_iterator_next (iter, (void *) &key, (void *) &ce) == 0)
  {
    /* If entry has not been updated, add to `keys' array */
    /* FIXME: Remove macro once "ce->interval" is of type cdtime_t. */
    if ((now - ce->last_update) >= TIME_T_TO_CDTIME_T (timeout_g * ce->interval))
    {
      char **tmp;

      tmp = (char **) realloc ((void *) keys,
	  (keys_len + 1) * sizeof (char *));
      if (tmp == NULL)
      {
	ERROR ("uc_check_timeout: realloc failed.");
	c_avl_iterator_destroy (iter);
	sfree (keys);
	pthread_mutex_unlock (&cache_lock);
	return (-1);
      }

      keys = tmp;
      keys[keys_len] = strdup (key);
      if (keys[keys_len] == NULL)
      {
	ERROR ("uc_check_timeout: strdup failed.");
	continue;
      }
      keys_len++;
    }
  } /* while (c_avl_iterator_next) */

  ce = NULL;

  for (i = 0; i < keys_len; i++)
  {
    int status;

    status = ut_check_interesting (keys[i]);

    if (status < 0)
    {
      ERROR ("uc_check_timeout: ut_check_interesting failed.");
      sfree (keys[i]);
      continue;
    }
    else if (status == 0) /* ``service'' is uninteresting */
    {
      DEBUG ("uc_check_timeout: %s is missing but ``uninteresting''",
	  keys[i]);
      ce = NULL;
      status = c_avl_remove (cache_tree, keys[i],
	  (void *) &key, (void *) &ce);
      if (status != 0)
      {
	ERROR ("uc_check_timeout: c_avl_remove (%s) failed.", keys[i]);
      }
      sfree (keys[i]);
      sfree (key);
      if (ce != NULL)
        cache_free (ce);
      continue;
    }

    /* If we get here, the value is ``interesting''. Query the record from the
     * cache and update the state field. */
    if (c_avl_get (cache_tree, keys[i], (void *) &ce) != 0)
    {
      ERROR ("uc_check_timeout: cannot get data for %s from cache", keys[i]);
      /* Do not free `keys[i]' so a notification is sent further down. */
      continue;
    }
    assert (ce != NULL);

    if (status == 2) /* persist */
    {
      DEBUG ("uc_check_timeout: %s is missing, sending notification.",
	  keys[i]);
      ce->state = STATE_MISSING;
      /* Do not free `keys[i]' so a notification is sent further down. */
    }
    else if (status == 1) /* do not persist */
    {
      if (ce->state == STATE_MISSING)
      {
	DEBUG ("uc_check_timeout: %s is missing but "
	    "notification has already been sent.",
	    keys[i]);
	/* Set `keys[i]' to NULL to no notification is sent. */
	sfree (keys[i]);
      }
      else /* (ce->state != STATE_MISSING) */
      {
	DEBUG ("uc_check_timeout: %s is missing, sending one notification.",
	    keys[i]);
	ce->state = STATE_MISSING;
	/* Do not free `keys[i]' so a notification is sent further down. */
      }
    }
    else
    {
      WARNING ("uc_check_timeout: ut_check_interesting (%s) returned "
	  "invalid status %i.",
	  keys[i], status);
      sfree (keys[i]);
    }

    /* Make really sure the next iteration doesn't work with this pointer.
     * There have been too many bugs in the past.. :/  -- octo */
    ce = NULL;
  } /* for (keys[i]) */

  c_avl_iterator_destroy (iter);

  pthread_mutex_unlock (&cache_lock);

  for (i = 0; i < keys_len; i++)
  {
    if (keys[i] == NULL)
      continue;

    uc_send_notification (keys[i]);
    sfree (keys[i]);
  }

  sfree (keys);

  return (0);
} /* int uc_check_timeout */
Пример #8
0
int uc_get_names (char ***ret_names, cdtime_t **ret_times, size_t *ret_number)
{
    c_avl_iterator_t *iter;
    char *key;
    cache_entry_t *value;

    char **names = NULL;
    cdtime_t *times = NULL;
    size_t number = 0;
    size_t size_arrays = 0;

    int status = 0;

    if ((ret_names == NULL) || (ret_number == NULL))
        return (-1);

    pthread_mutex_lock (&cache_lock);

    size_arrays = (size_t) c_avl_size (cache_tree);
    if (size_arrays < 1)
    {
        /* Handle the "no values" case here, to avoid the error message when
         * calloc() returns NULL. */
        pthread_mutex_unlock (&cache_lock);
        return (0);
    }

    names = calloc (size_arrays, sizeof (*names));
    times = calloc (size_arrays, sizeof (*times));
    if ((names == NULL) || (times == NULL))
    {
        ERROR ("uc_get_names: calloc failed.");
        sfree (names);
        sfree (times);
        pthread_mutex_unlock (&cache_lock);
        return (ENOMEM);
    }

    iter = c_avl_get_iterator (cache_tree);
    while (c_avl_iterator_next (iter, (void *) &key, (void *) &value) == 0)
    {
        /* remove missing values when list values */
        if (value->state == STATE_MISSING)
            continue;

        /* c_avl_size does not return a number smaller than the number of elements
         * returned by c_avl_iterator_next. */
        assert (number < size_arrays);

        if (ret_times != NULL)
            times[number] = value->last_time;

        names[number] = strdup (key);
        if (names[number] == NULL)
        {
            status = -1;
            break;
        }

        number++;
    } /* while (c_avl_iterator_next) */

    c_avl_iterator_destroy (iter);
    pthread_mutex_unlock (&cache_lock);

    if (status != 0)
    {
        size_t i;

        for (i = 0; i < number; i++)
        {
            sfree (names[i]);
        }
        sfree (names);
        sfree (times);

        return (-1);
    }

    *ret_names = names;
    if (ret_times != NULL)
        *ret_times = times;
    else
        sfree (times);
    *ret_number = number;

    return (0);
} /* int uc_get_names */
Пример #9
0
int uc_check_timeout (void)
{
    cdtime_t now;
    cache_entry_t *ce;

    char **keys = NULL;
    cdtime_t *keys_time = NULL;
    cdtime_t *keys_interval = NULL;
    int keys_len = 0;

    char *key;
    c_avl_iterator_t *iter;

    int status;
    int i;

    pthread_mutex_lock (&cache_lock);

    now = cdtime ();

    /* Build a list of entries to be flushed */
    iter = c_avl_get_iterator (cache_tree);
    while (c_avl_iterator_next (iter, (void *) &key, (void *) &ce) == 0)
    {
        char **tmp;
        cdtime_t *tmp_time;

        /* If the entry is fresh enough, continue. */
        if ((now - ce->last_update) < (ce->interval * timeout_g))
            continue;

        /* If entry has not been updated, add to `keys' array */
        tmp = realloc ((void *) keys,
                       (keys_len + 1) * sizeof (char *));
        if (tmp == NULL)
        {
            ERROR ("uc_check_timeout: realloc failed.");
            continue;
        }
        keys = tmp;

        tmp_time = realloc (keys_time, (keys_len + 1) * sizeof (*keys_time));
        if (tmp_time == NULL)
        {
            ERROR ("uc_check_timeout: realloc failed.");
            continue;
        }
        keys_time = tmp_time;

        tmp_time = realloc (keys_interval, (keys_len + 1) * sizeof (*keys_interval));
        if (tmp_time == NULL)
        {
            ERROR ("uc_check_timeout: realloc failed.");
            continue;
        }
        keys_interval = tmp_time;

        keys[keys_len] = strdup (key);
        if (keys[keys_len] == NULL)
        {
            ERROR ("uc_check_timeout: strdup failed.");
            continue;
        }
        keys_time[keys_len] = ce->last_time;
        keys_interval[keys_len] = ce->interval;

        keys_len++;
    } /* while (c_avl_iterator_next) */

    c_avl_iterator_destroy (iter);
    pthread_mutex_unlock (&cache_lock);

    if (keys_len == 0)
    {
        /* realloc() may have been called for these. */
        sfree (keys);
        sfree (keys_time);
        sfree (keys_interval);
        return (0);
    }

    /* Call the "missing" callback for each value. Do this before removing the
     * value from the cache, so that callbacks can still access the data stored,
     * including plugin specific meta data, rates, history, …. This must be done
     * without holding the lock, otherwise we will run into a deadlock if a
     * plugin calls the cache interface. */
    for (i = 0; i < keys_len; i++)
    {
        value_list_t vl = VALUE_LIST_INIT;

        vl.values = NULL;
        vl.values_len = 0;
        vl.meta = NULL;

        status = parse_identifier_vl (keys[i], &vl);
        if (status != 0)
        {
            ERROR ("uc_check_timeout: parse_identifier_vl (\"%s\") failed.", keys[i]);
            continue;
        }

        vl.time = keys_time[i];
        vl.interval = keys_interval[i];

        plugin_dispatch_missing (&vl);
    } /* for (i = 0; i < keys_len; i++) */

    /* Now actually remove all the values from the cache. We don't re-evaluate
     * the timestamp again, so in theory it is possible we remove a value after
     * it is updated here. */
    pthread_mutex_lock (&cache_lock);
    for (i = 0; i < keys_len; i++)
    {
        key = NULL;
        ce = NULL;

        status = c_avl_remove (cache_tree, keys[i],
                               (void *) &key, (void *) &ce);
        if (status != 0)
        {
            ERROR ("uc_check_timeout: c_avl_remove (\"%s\") failed.", keys[i]);
            sfree (keys[i]);
            continue;
        }

        sfree (keys[i]);
        sfree (key);
        cache_free (ce);
    } /* for (i = 0; i < keys_len; i++) */
    pthread_mutex_unlock (&cache_lock);

    sfree (keys);
    sfree (keys_time);
    sfree (keys_interval);

    return (0);
} /* int uc_check_timeout */