9ea68d4c7e3cefdba7151fb8b11b7dd3bd5be5e4
1 /*****************************************************************************
2 * RRDtool 1.3.8 Copyright by Tobi Oetiker, 1997-2009
3 *****************************************************************************
4 * rrd_info Get Information about the configuration of an RRD
5 *****************************************************************************/
7 #include "rrd_tool.h"
8 #include "rrd_rpncalc.h"
9 #include <stdarg.h>
11 #ifdef WIN32
12 #include <stdlib.h>
13 #endif
15 /* proto */
16 rrd_info_t *rrd_info(
17 int,
18 char **);
19 rrd_info_t *rrd_info_r(
20 char *filename);
22 /* allocate memory for string */
23 char *sprintf_alloc(
24 char *fmt,
25 ...)
26 {
27 char *str = NULL;
28 va_list argp;
29 #ifdef HAVE_VASPRINTF
30 va_start( argp, fmt );
31 vasprintf( &str, fmt, argp );
32 #else
33 int maxlen = 1024 + strlen(fmt);
34 str = (char*)(malloc(sizeof(char) * (maxlen + 1)));
35 if (str != NULL) {
36 va_start(argp, fmt);
37 #ifdef HAVE_VSNPRINTF
38 vsnprintf(str, maxlen, fmt, argp);
39 #else
40 vsprintf(str, fmt, argp);
41 #endif
42 }
43 #endif // HAVE_VASPRINTF
44 va_end(argp);
45 return str;
46 }
48 /* the function formerly known as push was renamed to info_push and later
49 * rrd_info_push because it is now used outside the scope of this file */
50 rrd_info_t
51 * rrd_info_push(rrd_info_t * info,
52 char *key, rrd_info_type_t type, rrd_infoval_t value)
53 {
54 rrd_info_t *next;
56 next = (rrd_info_t*)(malloc(sizeof(*next)));
57 next->next = (rrd_info_t *) 0;
58 if (info)
59 info->next = next;
60 next->type = type;
61 next->key = key;
62 switch (type) {
63 case RD_I_VAL:
64 next->value.u_val = value.u_val;
65 break;
66 case RD_I_CNT:
67 next->value.u_cnt = value.u_cnt;
68 break;
69 case RD_I_INT:
70 next->value.u_int = value.u_int;
71 break;
72 case RD_I_STR:
73 next->value.u_str = (char*)(malloc(sizeof(char) * (strlen(value.u_str) + 1)));
74 strcpy(next->value.u_str, value.u_str);
75 break;
76 case RD_I_BLO:
77 next->value.u_blo.size = value.u_blo.size;
78 next->value.u_blo.ptr =
79 (unsigned char*)malloc(sizeof(unsigned char) * value.u_blo.size);
80 memcpy(next->value.u_blo.ptr, value.u_blo.ptr, value.u_blo.size);
81 break;
82 }
83 return (next);
84 }
87 rrd_info_t *rrd_info(
88 int argc,
89 char **argv)
90 {
91 rrd_info_t *info;
93 if (argc < 2) {
94 rrd_set_error("please specify an rrd");
95 return NULL;
96 }
98 info = rrd_info_r(argv[1]);
100 return (info);
101 }
105 rrd_info_t *rrd_info_r(
106 char *filename)
107 {
108 unsigned int i, ii = 0;
109 rrd_t rrd;
110 rrd_info_t *data = NULL, *cd;
111 rrd_infoval_t info;
112 rrd_file_t *rrd_file;
113 enum cf_en current_cf;
114 enum dst_en current_ds;
116 rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
117 if (rrd_file == NULL)
118 goto err_free;
120 info.u_str = filename;
121 cd = rrd_info_push(NULL, sprintf_alloc("filename"), RD_I_STR, info);
122 data = cd;
124 info.u_str = rrd.stat_head->version;
125 cd = rrd_info_push(cd, sprintf_alloc("rrd_version"), RD_I_STR, info);
127 info.u_cnt = rrd.stat_head->pdp_step;
128 cd = rrd_info_push(cd, sprintf_alloc("step"), RD_I_CNT, info);
130 info.u_cnt = rrd.live_head->last_up;
131 cd = rrd_info_push(cd, sprintf_alloc("last_update"), RD_I_CNT, info);
133 for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
135 info.u_str = rrd.ds_def[i].dst;
136 cd = rrd_info_push(cd, sprintf_alloc("ds[%s].type",
137 rrd.ds_def[i].ds_nam),
138 RD_I_STR, info);
140 current_ds = dst_conv(rrd.ds_def[i].dst);
141 switch (current_ds) {
142 case DST_CDEF:
143 {
144 char *buffer = NULL;
146 rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),
147 rrd.ds_def, &buffer);
148 info.u_str = buffer;
149 cd = rrd_info_push(cd,
150 sprintf_alloc("ds[%s].cdef",
151 rrd.ds_def[i].ds_nam), RD_I_STR,
152 info);
153 free(buffer);
154 }
155 break;
156 default:
157 info.u_cnt = rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt;
158 cd = rrd_info_push(cd,
159 sprintf_alloc("ds[%s].minimal_heartbeat",
160 rrd.ds_def[i].ds_nam), RD_I_CNT,
161 info);
163 info.u_val = rrd.ds_def[i].par[DS_min_val].u_val;
164 cd = rrd_info_push(cd,
165 sprintf_alloc("ds[%s].min",
166 rrd.ds_def[i].ds_nam), RD_I_VAL,
167 info);
169 info.u_val = rrd.ds_def[i].par[DS_max_val].u_val;
170 cd = rrd_info_push(cd,
171 sprintf_alloc("ds[%s].max",
172 rrd.ds_def[i].ds_nam), RD_I_VAL,
173 info);
174 break;
175 }
177 info.u_str = rrd.pdp_prep[i].last_ds;
178 cd = rrd_info_push(cd,
179 sprintf_alloc("ds[%s].last_ds",
180 rrd.ds_def[i].ds_nam), RD_I_STR,
181 info);
183 info.u_val = rrd.pdp_prep[i].scratch[PDP_val].u_val;
184 cd = rrd_info_push(cd,
185 sprintf_alloc("ds[%s].value",
186 rrd.ds_def[i].ds_nam), RD_I_VAL,
187 info);
189 info.u_cnt = rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt;
190 cd = rrd_info_push(cd,
191 sprintf_alloc("ds[%s].unknown_sec",
192 rrd.ds_def[i].ds_nam), RD_I_CNT,
193 info);
194 }
196 for (i = 0; i < rrd.stat_head->rra_cnt; i++) {
197 info.u_str = rrd.rra_def[i].cf_nam;
198 cd = rrd_info_push(cd, sprintf_alloc("rra[%d].cf", i), RD_I_STR,
199 info);
200 current_cf = cf_conv(rrd.rra_def[i].cf_nam);
202 info.u_cnt = rrd.rra_def[i].row_cnt;
203 cd = rrd_info_push(cd, sprintf_alloc("rra[%d].rows", i), RD_I_CNT,
204 info);
206 info.u_cnt = rrd.rra_ptr[i].cur_row;
207 cd = rrd_info_push(cd, sprintf_alloc("rra[%d].cur_row", i), RD_I_CNT,
208 info);
210 info.u_cnt = rrd.rra_def[i].pdp_cnt;
211 cd = rrd_info_push(cd, sprintf_alloc("rra[%d].pdp_per_row", i),
212 RD_I_CNT, info);
214 switch (current_cf) {
215 case CF_HWPREDICT:
216 case CF_MHWPREDICT:
217 info.u_val = rrd.rra_def[i].par[RRA_hw_alpha].u_val;
218 cd = rrd_info_push(cd, sprintf_alloc("rra[%d].alpha", i),
219 RD_I_VAL, info);
220 info.u_val = rrd.rra_def[i].par[RRA_hw_beta].u_val;
221 cd = rrd_info_push(cd, sprintf_alloc("rra[%d].beta", i), RD_I_VAL,
222 info);
223 break;
224 case CF_SEASONAL:
225 case CF_DEVSEASONAL:
226 info.u_val = rrd.rra_def[i].par[RRA_seasonal_gamma].u_val;
227 cd = rrd_info_push(cd, sprintf_alloc("rra[%d].gamma", i),
228 RD_I_VAL, info);
229 if (atoi(rrd.stat_head->version) >= 4) {
230 info.u_val =
231 rrd.rra_def[i].par[RRA_seasonal_smoothing_window].u_val;
232 cd = rrd_info_push(cd,
233 sprintf_alloc("rra[%d].smoothing_window",
234 i), RD_I_VAL, info);
235 }
236 break;
237 case CF_FAILURES:
238 info.u_val = rrd.rra_def[i].par[RRA_delta_pos].u_val;
239 cd = rrd_info_push(cd, sprintf_alloc("rra[%d].delta_pos", i),
240 RD_I_VAL, info);
241 info.u_val = rrd.rra_def[i].par[RRA_delta_neg].u_val;
242 cd = rrd_info_push(cd, sprintf_alloc("rra[%d].delta_neg", i),
243 RD_I_VAL, info);
244 info.u_cnt = rrd.rra_def[i].par[RRA_failure_threshold].u_cnt;
245 cd = rrd_info_push(cd,
246 sprintf_alloc("rra[%d].failure_threshold", i),
247 RD_I_CNT, info);
248 info.u_cnt = rrd.rra_def[i].par[RRA_window_len].u_cnt;
249 cd = rrd_info_push(cd, sprintf_alloc("rra[%d].window_length", i),
250 RD_I_CNT, info);
251 break;
252 case CF_DEVPREDICT:
253 break;
254 default:
255 info.u_val = rrd.rra_def[i].par[RRA_cdp_xff_val].u_val;
256 cd = rrd_info_push(cd, sprintf_alloc("rra[%d].xff", i), RD_I_VAL,
257 info);
258 break;
259 }
261 for (ii = 0; ii < rrd.stat_head->ds_cnt; ii++) {
262 switch (current_cf) {
263 case CF_HWPREDICT:
264 case CF_MHWPREDICT:
265 info.u_val =
266 rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
267 ii].scratch[CDP_hw_intercept].u_val;
268 cd = rrd_info_push(cd,
269 sprintf_alloc
270 ("rra[%d].cdp_prep[%d].intercept", i, ii),
271 RD_I_VAL, info);
272 info.u_val =
273 rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
274 ii].scratch[CDP_hw_slope].u_val;
275 cd = rrd_info_push(cd,
276 sprintf_alloc("rra[%d].cdp_prep[%d].slope",
277 i, ii), RD_I_VAL, info);
278 info.u_cnt =
279 rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
280 ii].scratch[CDP_null_count].u_cnt;
281 cd = rrd_info_push(cd,
282 sprintf_alloc
283 ("rra[%d].cdp_prep[%d].NaN_count", i, ii),
284 RD_I_CNT, info);
285 break;
286 case CF_SEASONAL:
287 info.u_val =
288 rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
289 ii].scratch[CDP_hw_seasonal].u_val;
290 cd = rrd_info_push(cd,
291 sprintf_alloc
292 ("rra[%d].cdp_prep[%d].seasonal", i, ii),
293 RD_I_VAL, info);
294 break;
295 case CF_DEVSEASONAL:
296 info.u_val =
297 rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
298 ii].scratch[CDP_seasonal_deviation].u_val;
299 cd = rrd_info_push(cd,
300 sprintf_alloc
301 ("rra[%d].cdp_prep[%d].deviation", i, ii),
302 RD_I_VAL, info);
303 break;
304 case CF_DEVPREDICT:
305 break;
306 case CF_FAILURES:
307 {
308 unsigned short j;
309 char *violations_array;
310 char history[MAX_FAILURES_WINDOW_LEN + 1];
312 violations_array =
313 (char *) rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
314 ii].scratch;
315 for (j = 0; j < rrd.rra_def[i].par[RRA_window_len].u_cnt; ++j)
316 history[j] = (violations_array[j] == 1) ? '1' : '0';
317 history[j] = '\0';
318 info.u_str = history;
319 cd = rrd_info_push(cd,
320 sprintf_alloc
321 ("rra[%d].cdp_prep[%d].history", i, ii),
322 RD_I_STR, info);
323 }
324 break;
325 default:
326 info.u_val =
327 rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
328 ii].scratch[CDP_val].u_val;
329 cd = rrd_info_push(cd,
330 sprintf_alloc("rra[%d].cdp_prep[%d].value",
331 i, ii), RD_I_VAL, info);
332 info.u_cnt =
333 rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
334 ii].scratch[CDP_unkn_pdp_cnt].u_cnt;
335 cd = rrd_info_push(cd,
336 sprintf_alloc
337 ("rra[%d].cdp_prep[%d].unknown_datapoints",
338 i, ii), RD_I_CNT, info);
339 break;
340 }
341 }
342 }
344 rrd_close(rrd_file);
345 err_free:
346 rrd_free(&rrd);
347 return (data);
348 }
351 void rrd_info_print(
352 rrd_info_t * data)
353 {
354 while (data) {
355 printf("%s = ", data->key);
357 switch (data->type) {
358 case RD_I_VAL:
359 if (isnan(data->value.u_val))
360 printf("NaN\n");
361 else
362 printf("%0.10e\n", data->value.u_val);
363 break;
364 case RD_I_CNT:
365 printf("%lu\n", data->value.u_cnt);
366 break;
367 case RD_I_INT:
368 printf("%d\n", data->value.u_int);
369 break;
370 case RD_I_STR:
371 printf("\"%s\"\n", data->value.u_str);
372 break;
373 case RD_I_BLO:
374 printf("BLOB_SIZE:%lu\n", data->value.u_blo.size);
375 fwrite(data->value.u_blo.ptr, data->value.u_blo.size, 1, stdout);
376 break;
377 }
378 data = data->next;
379 }
380 }
382 void rrd_info_free(
383 rrd_info_t * data)
384 {
385 rrd_info_t *save;
387 while (data) {
388 save = data;
389 if (data->key) {
390 if (data->type == RD_I_STR) {
391 free(data->value.u_str);
392 }
393 if (data->type == RD_I_BLO) {
394 free(data->value.u_blo.ptr);
395 }
396 free(data->key);
397 }
398 data = data->next;
399 free(save);
400 }
401 }