Code

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