Announce of VDEF in rrd_graph
[rrdtool.git] / src / rrd_dump.c
1 /*****************************************************************************
2  * RRDtool 1.0.33  Copyright Tobias Oetiker, 1997 - 2000
3  *****************************************************************************
4  * rrd_dump  Display a RRD
5  *****************************************************************************
6  * $Id$
7  * $Log$
8  * Revision 1.3  2001/03/10 23:54:39  oetiker
9  * Support for COMPUTE data sources (CDEF data sources). Removes the RPN
10  * parser and calculator from rrd_graph and puts then in a new file,
11  * rrd_rpncalc.c. Changes to core files rrd_create and rrd_update. Some
12  * clean-up of aberrant behavior stuff, including a bug fix.
13  * Documentation update (rrdcreate.pod, rrdupdate.pod). Change xml format.
14  * -- Jake Brutlag <jakeb@corp.webtv.net>
15  *
16  * Revision 1.2  2001/03/04 13:01:55  oetiker
17  *
18  * Revision 1.1.1.1  2001/02/25 22:25:05  oetiker
19  * checkin
20  *
21  *****************************************************************************/
22
23 #include "rrd_tool.h"
24 #include "rrd_rpncalc.h"
25
26 extern char *tzname[2];
27
28 int
29 rrd_dump(int argc, char **argv)    
30 {   
31     int          i,ii,ix,iii=0;
32     time_t       now;
33     char         somestring[255];
34     rrd_value_t  my_cdp;
35     long         rra_base, rra_start, rra_next;
36     FILE                  *in_file;
37     rrd_t             rrd;
38     rrd_value_t  value;
39
40     if(rrd_open(argv[1],&in_file,&rrd, RRD_READONLY)==-1){
41         return(-1);
42     }
43
44     puts("<!-- Round Robin Database Dump -->");
45     puts("<rrd>");
46     printf("\t<version> %s </version>\n",RRD_VERSION);
47     printf("\t<step> %lu </step> <!-- Seconds -->\n",rrd.stat_head->pdp_step);
48 #if HAVE_STRFTIME
49     strftime(somestring,200,"%Y-%m-%d %H:%M:%S %Z",
50              localtime(&rrd.live_head->last_up));
51 #else
52 # error "Need strftime"
53 #endif
54     printf("\t<lastupdate> %ld </lastupdate> <!-- %s -->\n\n",
55            rrd.live_head->last_up,somestring);
56     for(i=0;i<rrd.stat_head->ds_cnt;i++){
57         printf("\t<ds>\n");
58         printf("\t\t<name> %s </name>\n",rrd.ds_def[i].ds_nam);
59         printf("\t\t<type> %s </type>\n",rrd.ds_def[i].dst);
60     if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
61         printf("\t\t<minimal_heartbeat> %lu </minimal_heartbeat>\n",rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt);
62         if (isnan(rrd.ds_def[i].par[DS_min_val].u_val)){
63           printf("\t\t<min> NaN </min>\n");
64         } else {
65           printf("\t\t<min> %0.10e </min>\n",rrd.ds_def[i].par[DS_min_val].u_val);
66         }
67         if (isnan(rrd.ds_def[i].par[DS_max_val].u_val)){
68           printf("\t\t<max> NaN </max>\n");
69         } else {
70           printf("\t\t<max> %0.10e </max>\n",rrd.ds_def[i].par[DS_max_val].u_val);
71         }
72     } else { /* DST_CDEF */
73           char *str;
74           rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),rrd.ds_def,&str);
75           printf("\t\t<cdef> %s </cdef>\n", str);
76           free(str);
77         }
78         printf("\n\t\t<!-- PDP Status -->\n");
79         printf("\t\t<last_ds> %s </last_ds>\n",rrd.pdp_prep[i].last_ds);
80         if (isnan(rrd.pdp_prep[i].scratch[PDP_val].u_val)){
81           printf("\t\t<value> NaN </value>\n");
82         } else {
83           printf("\t\t<value> %0.10e </value>\n",rrd.pdp_prep[i].scratch[PDP_val].u_val);
84         }
85         printf("\t\t<unknown_sec> %lu </unknown_sec>\n",
86                rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
87         
88         printf("\t</ds>\n\n");
89     }
90
91     puts("<!-- Round Robin Archives -->");
92
93     rra_base=ftell(in_file);    
94     rra_next = rra_base;
95
96     for(i=0;i<rrd.stat_head->rra_cnt;i++){
97         
98         long timer=0;
99         rra_start= rra_next;
100         rra_next +=  ( rrd.stat_head->ds_cnt
101                       * rrd.rra_def[i].row_cnt
102                       * sizeof(rrd_value_t));
103         printf("\t<rra>\n");
104         printf("\t\t<cf> %s </cf>\n",rrd.rra_def[i].cf_nam);
105         printf("\t\t<pdp_per_row> %lu </pdp_per_row> <!-- %lu seconds -->\n\n",
106                rrd.rra_def[i].pdp_cnt, rrd.rra_def[i].pdp_cnt
107                *rrd.stat_head->pdp_step);
108         /* support for RRA parameters */
109         printf("\t\t<params>\n");
110         switch(cf_conv(rrd.rra_def[i].cf_nam)) {
111         case CF_HWPREDICT:
112            printf("\t\t<hw_alpha> %0.10e </hw_alpha>\n", 
113                   rrd.rra_def[i].par[RRA_hw_alpha].u_val);
114            printf("\t\t<hw_beta> %0.10e </hw_beta>\n", 
115                   rrd.rra_def[i].par[RRA_hw_beta].u_val);
116            printf("\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
117                   rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
118            break;
119         case CF_SEASONAL:
120         case CF_DEVSEASONAL:
121            printf("\t\t<seasonal_gamma> %0.10e </seasonal_gamma>\n", 
122                   rrd.rra_def[i].par[RRA_seasonal_gamma].u_val);
123            printf("\t\t<seasonal_smooth_idx> %lu </seasonal_smooth_idx>\n",
124                   rrd.rra_def[i].par[RRA_seasonal_smooth_idx].u_cnt);
125            printf("\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
126                   rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
127            break;
128         case CF_FAILURES:
129            printf("\t\t<delta_pos> %0.10e </delta_pos>\n", 
130                   rrd.rra_def[i].par[RRA_delta_pos].u_val);
131            printf("\t\t<delta_neg> %0.10e </delta_neg>\n", 
132                   rrd.rra_def[i].par[RRA_delta_neg].u_val);
133            printf("\t\t<window_len> %lu </window_len>\n",
134                   rrd.rra_def[i].par[RRA_window_len].u_cnt);
135            printf("\t\t<failure_threshold> %lu </failure_threshold>\n",
136                   rrd.rra_def[i].par[RRA_failure_threshold].u_cnt);
137                   /* fall thru */
138         case CF_DEVPREDICT:
139            printf("\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
140                   rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
141            break;
142         case CF_AVERAGE:
143         case CF_MAXIMUM:
144         case CF_MINIMUM:
145         case CF_LAST:
146         default:
147            printf("\t\t<xff> %0.10e </xff>\n", rrd.rra_def[i].par[RRA_cdp_xff_val].u_val);
148            break;
149         }
150         printf("\t\t</params>\n");
151         printf("\t\t<cdp_prep>\n");
152         for(ii=0;ii<rrd.stat_head->ds_cnt;ii++){
153                 unsigned long ivalue;
154                 printf("\t\t\t<ds>\n");
155                 /* support for exporting all CDP parameters */
156                 /* parameters common to all CFs */
157                     /* primary_val and secondary_val do not need to be saved between updates
158                          * so strictly speaking they could be omitted.
159                          * However, they can be useful for diagnostic purposes, so are included here. */
160                 value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt
161                            +ii].scratch[CDP_primary_val].u_val;
162                         if (isnan(value)) {
163                            printf("\t\t\t<primary_value> NaN </primary_value>\n");
164                         } else {
165                            printf("\t\t\t<primary_value> %0.10e </primary_value>\n", value);
166                         }
167                 value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_secondary_val].u_val;
168                         if (isnan(value)) {
169                            printf("\t\t\t<secondary_value> NaN </secondary_value>\n");
170                         } else {
171                            printf("\t\t\t<secondary_value> %0.10e </secondary_value>\n", value);
172                         }
173                 switch(cf_conv(rrd.rra_def[i].cf_nam)) {
174                 case CF_HWPREDICT:
175                 value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_intercept].u_val;
176                         if (isnan(value)) {
177                            printf("\t\t\t<intercept> NaN </intercept>\n");
178                         } else {
179                            printf("\t\t\t<intercept> %0.10e </intercept>\n", value);
180                         }
181                 value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_last_intercept].u_val;
182                         if (isnan(value)) {
183                            printf("\t\t\t<last_intercept> NaN </last_intercept>\n");
184                         } else {
185                            printf("\t\t\t<last_intercept> %0.10e </last_intercept>\n", value);
186                         }
187                 value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_slope].u_val;
188                         if (isnan(value)) {
189                            printf("\t\t\t<slope> NaN </slope>\n");
190                         } else {
191                            printf("\t\t\t<slope> %0.10e </slope>\n", value);
192                         }
193                 value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_last_slope].u_val;
194                         if (isnan(value)) {
195                            printf("\t\t\t<last_slope> NaN </last_slope>\n");
196                         } else {
197                            printf("\t\t\t<last_slope> %0.10e </last_slope>\n", value);
198                         }
199                         ivalue = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_null_count].u_cnt;
200                         printf("\t\t\t<nan_count> %lu </nan_count>\n", ivalue);
201                         ivalue = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_last_null_count].u_cnt;
202                         printf("\t\t\t<last_nan_count> %lu </last_nan_count>\n", ivalue);
203                         break;
204                 case CF_SEASONAL:
205                 case CF_DEVSEASONAL:
206                 value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_seasonal].u_val;
207                         if (isnan(value)) {
208                            printf("\t\t\t<seasonal> NaN </seasonal>\n");
209                         } else {
210                            printf("\t\t\t<seasonal> %0.10e </seasonal>\n", value);
211                         }
212                 value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_last_seasonal].u_val;
213                         if (isnan(value)) {
214                            printf("\t\t\t<last_seasonal> NaN </last_seasonal>\n");
215                         } else {
216                            printf("\t\t\t<last_seasonal> %0.10e </last_seasonal>\n", value);
217                         }
218                 ivalue = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_init_seasonal].u_cnt;
219                         printf("\t\t\t<init_flag> %lu </init_flag>\n", ivalue);
220                         break;
221                 case CF_DEVPREDICT:
222                         break;
223                 case CF_FAILURES:
224                     {
225             short vidx;
226                         char *violations_array = (char *) ((void*) 
227                            rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch);
228                         printf("\t\t\t<history> ");
229                         for (vidx = 0; vidx < rrd.rra_def[i].par[RRA_window_len].u_cnt; ++vidx)
230                         {
231                                 printf("%d",violations_array[vidx]);
232                         }
233                         printf(" </history>\n");
234                         }
235                         break;
236                 case CF_AVERAGE:
237                 case CF_MAXIMUM:
238                 case CF_MINIMUM:
239                 case CF_LAST:
240                 default:
241                 value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_val].u_val;
242                         if (isnan(value)) {
243                            printf("\t\t\t<value> NaN </value>\n");
244                         } else {
245                            printf("\t\t\t<value> %0.10e </value>\n", value);
246                         }
247                     printf("\t\t\t<unknown_datapoints> %lu </unknown_datapoints>\n",
248                        rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_unkn_pdp_cnt].u_cnt);
249                         break;
250                 }
251         printf("\t\t\t</ds>\n");         
252     }
253         printf("\t\t</cdp_prep>\n");
254
255         printf("\t\t<database>\n");
256         fseek(in_file,(rra_start
257                        +(rrd.rra_ptr[i].cur_row+1)
258                        * rrd.stat_head->ds_cnt
259                        * sizeof(rrd_value_t)),SEEK_SET);
260         timer = - (rrd.rra_def[i].row_cnt-1);
261         ii=rrd.rra_ptr[i].cur_row;
262         for(ix=0;ix<rrd.rra_def[i].row_cnt;ix++){           
263             ii++;
264             if (ii>=rrd.rra_def[i].row_cnt) {
265                 fseek(in_file,rra_start,SEEK_SET);
266                 ii=0; /* wrap if max row cnt is reached */
267             }
268             now = (rrd.live_head->last_up 
269                    - rrd.live_head->last_up 
270                    % (rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step)) 
271                 + (timer*rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step);
272
273             timer++;
274 #if HAVE_STRFTIME
275             strftime(somestring,200,"%Y-%m-%d %H:%M:%S %Z", localtime(&now));
276 #else
277 # error "Need strftime"
278 #endif
279             printf("\t\t\t<!-- %s / %d --> <row>",somestring,(int)now);
280             for(iii=0;iii<rrd.stat_head->ds_cnt;iii++){                  
281                 fread(&my_cdp,sizeof(rrd_value_t),1,in_file);           
282                 if (isnan(my_cdp)){
283                   printf("<v> NaN </v>");
284                 } else {
285                   printf("<v> %0.10e </v>",my_cdp);
286                 };
287             }
288             printf("</row>\n");
289         }
290         printf("\t\t</database>\n\t</rra>\n");
291         
292     }
293     printf("</rrd>\n");
294     rrd_free(&rrd);
295     fclose(in_file);
296     return(0);
297 }
298
299
300
301