1 /**
2 * collectd - src/utils_latency_config.c
3 * Copyright (C) 2013-2016 Florian octo Forster
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Florian octo Forster <octo at collectd.org>
25 * Pavel Rochnyack <pavel2000 at ngs.ru>
26 */
28 #include "utils_latency_config.h"
29 #include "collectd.h"
30 #include "common.h"
32 static int latency_config_add_percentile(latency_config_t *conf,
33 oconfig_item_t *ci,
34 const char *plugin) {
35 double percent;
36 int status = cf_util_get_double(ci, &percent);
37 if (status != 0)
38 return status;
40 if ((percent <= 0.0) || (percent >= 100)) {
41 ERROR("%s plugin: The value for \"%s\" must be between 0 and 100, "
42 "exclusively.",
43 plugin, ci->key);
44 return ERANGE;
45 }
47 double *tmp = realloc(conf->percentile,
48 sizeof(*conf->percentile) * (conf->percentile_num + 1));
49 if (tmp == NULL) {
50 ERROR("%s plugin: realloc failed.", plugin);
51 return ENOMEM;
52 }
53 conf->percentile = tmp;
54 conf->percentile[conf->percentile_num] = percent;
55 conf->percentile_num++;
57 return 0;
58 } /* int latency_config_add_percentile */
60 static int latency_config_add_bucket(latency_config_t *conf, oconfig_item_t *ci,
61 const char *plugin) {
62 if ((ci->values_num != 2) || (ci->values[0].type != OCONFIG_TYPE_NUMBER) ||
63 (ci->values[1].type != OCONFIG_TYPE_NUMBER)) {
64 ERROR("%s plugin: \"%s\" requires exactly two numeric arguments.", plugin,
65 ci->key);
66 return EINVAL;
67 }
69 if (ci->values[1].value.number &&
70 ci->values[1].value.number <= ci->values[0].value.number) {
71 ERROR("%s plugin: MIN must be less than MAX in \"%s\".", plugin, ci->key);
72 return ERANGE;
73 }
75 if (ci->values[0].value.number < 0) {
76 ERROR("%s plugin: MIN must be greater then or equal to zero in \"%s\".",
77 plugin, ci->key);
78 return ERANGE;
79 }
81 latency_bucket_t *tmp =
82 realloc(conf->buckets, sizeof(*conf->buckets) * (conf->buckets_num + 1));
83 if (tmp == NULL) {
84 ERROR("%s plugin: realloc failed.", plugin);
85 return ENOMEM;
86 }
87 conf->buckets = tmp;
88 conf->buckets[conf->buckets_num].lower_bound =
89 DOUBLE_TO_CDTIME_T(ci->values[0].value.number);
90 conf->buckets[conf->buckets_num].upper_bound =
91 DOUBLE_TO_CDTIME_T(ci->values[1].value.number);
92 conf->buckets_num++;
94 return (0);
95 } /* int latency_config_add_bucket */
97 int latency_config(latency_config_t *conf, oconfig_item_t *ci,
98 char const *plugin) {
99 int status = 0;
101 for (int i = 0; i < ci->children_num; i++) {
102 oconfig_item_t *child = ci->children + i;
104 if (strcasecmp("Percentile", child->key) == 0)
105 status = latency_config_add_percentile(conf, child, plugin);
106 else if (strcasecmp("Bucket", child->key) == 0)
107 status = latency_config_add_bucket(conf, child, plugin);
108 else
109 WARNING("%s plugin: \"%s\" is not a valid option within a \"%s\" block.",
110 plugin, child->key, ci->key);
112 if (status != 0)
113 return status;
114 }
116 if ((status == 0) && (conf->percentile_num == 0) &&
117 (conf->buckets_num == 0)) {
118 ERROR("%s plugin: The \"%s\" block must contain at least one "
119 "\"Percentile\" or \"Bucket\" option.",
120 plugin, ci->key);
121 return EINVAL;
122 }
124 return 0;
125 }
127 int latency_config_copy(latency_config_t *dst, const latency_config_t src) {
128 *dst = (latency_config_t){
129 .percentile_num = src.percentile_num, .buckets_num = src.buckets_num,
130 };
132 dst->percentile = calloc(dst->percentile_num, sizeof(*dst->percentile));
133 dst->buckets = calloc(dst->buckets_num, sizeof(*dst->buckets));
135 if ((dst->percentile == NULL) || (dst->buckets == NULL)) {
136 latency_config_free(*dst);
137 return ENOMEM;
138 }
140 memmove(dst->percentile, src.percentile,
141 dst->percentile_num * sizeof(*dst->percentile));
142 memmove(dst->buckets, src.buckets, dst->buckets_num * sizeof(*dst->buckets));
144 return 0;
145 } /* int latency_config_copy */
147 void latency_config_free(latency_config_t conf) {
148 sfree(conf.percentile);
149 sfree(conf.buckets);
150 } /* void latency_config_free */