Merge branch 'collectd-5.7' into collectd-5.8
[collectd.git] / src / utils_latency_config.c
index 7504aaf..5eb5b6d 100644 (file)
  *   Pavel Rochnyack <pavel2000 at ngs.ru>
  */
 
-#include "collectd.h"
-#include "common.h"
 #include "utils_latency_config.h"
+#include "common.h"
+#include "collectd.h"
 
-int latency_config_add_percentile (const char *plugin, latency_config_t *cl,
-    oconfig_item_t *ci)
-{
-  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
-  {
-    ERROR ("%s plugin: \"%s\" requires exactly one numeric argument.",
-             plugin, ci->key);
-    return (-1);
-  }
-
-  double percent = ci->values[0].value.number;
-  double *tmp;
-
-  if ((percent <= 0.0) || (percent >= 100))
-  {
-    ERROR ("%s plugin: The value for \"%s\" must be between 0 and 100, "
-        "exclusively.", plugin, ci->key);
-    return (ERANGE);
+static int latency_config_add_percentile(latency_config_t *conf,
+                                         oconfig_item_t *ci,
+                                         const char *plugin) {
+  double percent;
+  int status = cf_util_get_double(ci, &percent);
+  if (status != 0)
+    return status;
+
+  if ((percent <= 0.0) || (percent >= 100)) {
+    ERROR("%s plugin: The value for \"%s\" must be between 0 and 100, "
+          "exclusively.",
+          plugin, ci->key);
+    return ERANGE;
   }
 
-  tmp = realloc (cl->percentile,
-      sizeof (*cl->percentile) * (cl->percentile_num + 1));
-  if (tmp == NULL)
-  {
-    ERROR ("%s plugin: realloc failed.", plugin);
-    return (ENOMEM);
+  double *tmp = realloc(conf->percentile,
+                        sizeof(*conf->percentile) * (conf->percentile_num + 1));
+  if (tmp == NULL) {
+    ERROR("%s plugin: realloc failed.", plugin);
+    return ENOMEM;
   }
-  cl->percentile = tmp;
-  cl->percentile[cl->percentile_num] = percent;
-  cl->percentile_num++;
+  conf->percentile = tmp;
+  conf->percentile[conf->percentile_num] = percent;
+  conf->percentile_num++;
 
-  return (0);
+  return 0;
 } /* int latency_config_add_percentile */
 
-int latency_config_add_rate (const char *plugin, latency_config_t *cl,
-    oconfig_item_t *ci)
-{
-
-  if ((ci->values_num != 2)
-    ||(ci->values[0].type != OCONFIG_TYPE_NUMBER)
-    ||(ci->values[1].type != OCONFIG_TYPE_NUMBER))
-  {
-    ERROR ("%s plugin: \"%s\" requires exactly two numeric arguments.",
-             plugin, ci->key);
-    return (-1);
+static int latency_config_add_bucket(latency_config_t *conf, oconfig_item_t *ci,
+                                     const char *plugin) {
+  if ((ci->values_num != 2) || (ci->values[0].type != OCONFIG_TYPE_NUMBER) ||
+      (ci->values[1].type != OCONFIG_TYPE_NUMBER)) {
+    ERROR("%s plugin: \"%s\" requires exactly two numeric arguments.", plugin,
+          ci->key);
+    return EINVAL;
   }
 
   if (ci->values[1].value.number &&
-      ci->values[1].value.number <= ci->values[0].value.number)
-  {
-    ERROR ("%s plugin: MIN must be less than MAX in \"%s\".",
-             plugin, ci->key);
-    return (-1);
+      ci->values[1].value.number <= ci->values[0].value.number) {
+    ERROR("%s plugin: MIN must be less than MAX in \"%s\".", plugin, ci->key);
+    return ERANGE;
   }
 
-  if (ci->values[0].value.number < 0.001)
-  {
-    ERROR ("%s plugin: MIN must be greater or equal to 0.001 in \"%s\".",
-             plugin, ci->key);
-    return (-1);
+  if (ci->values[0].value.number < 0) {
+    ERROR("%s plugin: MIN must be greater then or equal to zero in \"%s\".",
+          plugin, ci->key);
+    return ERANGE;
   }
 
-  cdtime_t lower = DOUBLE_TO_CDTIME_T(ci->values[0].value.number);
-  cdtime_t upper = DOUBLE_TO_CDTIME_T(ci->values[1].value.number);
-  cdtime_t *tmp;
-
-  tmp = realloc (cl->rates,
-      sizeof (*cl->rates) * (cl->rates_num + 1) * 2);
-  if (tmp == NULL)
-  {
-    ERROR ("%s plugin: realloc failed.", plugin);
-    return (ENOMEM);
+  latency_bucket_t *tmp =
+      realloc(conf->buckets, sizeof(*conf->buckets) * (conf->buckets_num + 1));
+  if (tmp == NULL) {
+    ERROR("%s plugin: realloc failed.", plugin);
+    return ENOMEM;
+  }
+  conf->buckets = tmp;
+  conf->buckets[conf->buckets_num].lower_bound =
+      DOUBLE_TO_CDTIME_T(ci->values[0].value.number);
+  conf->buckets[conf->buckets_num].upper_bound =
+      DOUBLE_TO_CDTIME_T(ci->values[1].value.number);
+  conf->buckets_num++;
+
+  return 0;
+} /* int latency_config_add_bucket */
+
+int latency_config(latency_config_t *conf, oconfig_item_t *ci,
+                   char const *plugin) {
+  int status = 0;
+
+  for (int i = 0; i < ci->children_num; i++) {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp("Percentile", child->key) == 0)
+      status = latency_config_add_percentile(conf, child, plugin);
+    else if (strcasecmp("Bucket", child->key) == 0)
+      status = latency_config_add_bucket(conf, child, plugin);
+    else if (strcasecmp("BucketType", child->key) == 0)
+      status = cf_util_get_string(child, &conf->bucket_type);
+    else
+      WARNING("%s plugin: \"%s\" is not a valid option within a \"%s\" block.",
+              plugin, child->key, ci->key);
+
+    if (status != 0)
+      return status;
   }
-  cl->rates = tmp;
-  cl->rates[cl->rates_num * 2] = lower;
-  cl->rates[cl->rates_num * 2 + 1] = upper;
-  cl->rates_num++;
-
-  return (0);
-} /* int latency_config_add_rate */
-
-
-int latency_config_copy (latency_config_t *dst, const latency_config_t src)
-{
-  /* Copy percentiles configuration */
-  dst->percentile_num = src.percentile_num;
-  dst->percentile = malloc(sizeof (*dst->percentile) * (src.percentile_num));
-  if (dst->percentile == NULL)
-    goto nomem;
-
-  memcpy (dst->percentile, src.percentile,
-          (sizeof (*dst->percentile) * (src.percentile_num)));
-
-  if (src.percentile_type != NULL)
-  {
-    dst->percentile_type = strdup(src.percentile_type);
-    if (dst->percentile_type == NULL)
-      goto nomem;
+
+  if ((status == 0) && (conf->percentile_num == 0) &&
+      (conf->buckets_num == 0)) {
+    ERROR("%s plugin: The \"%s\" block must contain at least one "
+          "\"Percentile\" or \"Bucket\" option.",
+          plugin, ci->key);
+    return EINVAL;
   }
 
-  /* Copy rates configuration */
-  dst->rates_num = src.rates_num;
-  dst->rates = malloc(sizeof (*dst->rates) * (src.rates_num) * 2);
-  if (dst->rates == NULL)
-    goto nomem;
+  return 0;
+}
+
+int latency_config_copy(latency_config_t *dst, const latency_config_t src) {
+  *dst = (latency_config_t){
+      .percentile_num = src.percentile_num, .buckets_num = src.buckets_num,
+  };
 
-  memcpy (dst->rates, src.rates,
-          (sizeof (*dst->rates) * (src.rates_num) * 2));
+  dst->percentile = calloc(dst->percentile_num, sizeof(*dst->percentile));
+  dst->buckets = calloc(dst->buckets_num, sizeof(*dst->buckets));
 
-  if (src.rates_type != NULL)
-  {
-    dst->rates_type = strdup(src.rates_type);
-    if (dst->rates_type == NULL)
-      goto nomem;
+  if ((dst->percentile == NULL) || (dst->buckets == NULL)) {
+    latency_config_free(*dst);
+    return ENOMEM;
   }
 
-  return (0);
-nomem:
-  free (dst->rates);
-  free (dst->rates_type);
-  free (dst->percentile);
-  free (dst->percentile_type);
-  return (-1);
+  if (src.bucket_type != NULL) {
+    dst->bucket_type = strdup(src.bucket_type);
+    if (dst->bucket_type == NULL) {
+      latency_config_free(*dst);
+      return ENOMEM;
+    }
+  }
+
+  memmove(dst->percentile, src.percentile,
+          dst->percentile_num * sizeof(*dst->percentile));
+  memmove(dst->buckets, src.buckets, dst->buckets_num * sizeof(*dst->buckets));
+
+  return 0;
 } /* int latency_config_copy */
 
-void latency_config_free (latency_config_t lc)
-{
-  sfree (lc.rates);
-  sfree (lc.rates_type);
-  sfree (lc.percentile);
-  sfree (lc.percentile_type);
+void latency_config_free(latency_config_t conf) {
+  sfree(conf.percentile);
+  sfree(conf.buckets);
+  sfree(conf.bucket_type);
 } /* void latency_config_free */