~ubuntu-branches/ubuntu/maverick/rrdtool/maverick

« back to all changes in this revision

Viewing changes to src/rrd_dump.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum
  • Date: 2010-07-22 08:07:01 UTC
  • mfrom: (1.2.8 upstream) (3.1.6 sid)
  • Revision ID: james.westby@ubuntu.com-20100722080701-k46mgdfz6euxwqsm
Tags: 1.4.3-1ubuntu1
* Merge from debian unstable, Remaining changes:
  - debian/control: Don't build against ruby1.9 as we don't want
    it in main.
* require libdbi >= 0.8.3 to prevent aborts when using dbi datasources

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
 
 * RRDtool 1.3.8  Copyright by Tobi Oetiker, 1997-2009
 
2
 * RRDtool 1.4.3  Copyright by Tobi Oetiker, 1997-2010
3
3
 *****************************************************************************
4
4
 * rrd_dump  Display a RRD
5
5
 *****************************************************************************
6
 
 * $Id: rrd_dump.c 1801 2009-05-19 13:45:05Z oetiker $
 
6
 * $Id: rrd_dump.c 2042 2010-03-22 16:05:55Z oetiker $
7
7
 * $Log$
8
8
 * Revision 1.7  2004/05/25 20:53:21  oetiker
9
9
 * prevent small leak when resources are exhausted -- Mike Slifcak
41
41
 * checkin
42
42
 *
43
43
 *****************************************************************************/
44
 
 
45
 
#ifdef WIN32
46
 
#include <stdlib.h>
47
 
#endif
48
 
 
49
 
 
50
44
#include "rrd_tool.h"
51
45
#include "rrd_rpncalc.h"
 
46
#include "rrd_client.h"
52
47
 
53
 
#ifdef HAVE_LOCALE_H
54
48
#include <locale.h>
55
 
#endif
56
49
 
57
50
#if !(defined(NETWARE) || defined(WIN32))
58
51
extern char *tzname[2];
59
52
#endif
60
53
 
 
54
//Local prototypes
 
55
size_t rrd_dump_opt_cb_fileout(
 
56
    const void *data,
 
57
    size_t len,
 
58
    void *user);
61
59
 
62
60
int rrd_dump_opt_r(
63
61
    const char *filename,
64
62
    char *outname,
65
 
    int opt_noheader)
 
63
    int opt_noheader);
 
64
 
 
65
int rrd_dump_cb_r(
 
66
    const char *filename,
 
67
    int opt_header,
 
68
    rrd_output_callback_t cb,
 
69
    void *user)
66
70
{
67
71
    unsigned int i, ii, ix, iii = 0;
68
72
    time_t    now;
70
74
    rrd_value_t my_cdp;
71
75
    off_t     rra_base, rra_start, rra_next;
72
76
    rrd_file_t *rrd_file;
73
 
    FILE     *out_file;
74
77
    rrd_t     rrd;
75
78
    rrd_value_t value;
76
79
    struct tm tm;
77
80
    char *old_locale = "";
 
81
 
 
82
//These two macros are local defines to clean up visible code from its redndancy
 
83
//and make it easier to read.
 
84
#define CB_PUTS(str)                                            \
 
85
    cb((str), strlen((str)), user)
 
86
#define CB_FMTS(...) do {                                       \
 
87
    char buffer[256];                                           \
 
88
    snprintf (buffer, sizeof(buffer), __VA_ARGS__);             \
 
89
    CB_PUTS (buffer);                                           \
 
90
    } while (0)
 
91
//These macros are to be undefined at the end of this function
 
92
 
 
93
    //Check if we got a (valid) callback method
 
94
    if (!cb) {
 
95
        return (-1);
 
96
    }
 
97
 
 
98
    rrd_init(&rrd);
 
99
 
78
100
    rrd_file = rrd_open(filename, &rrd, RRD_READONLY | RRD_READAHEAD);
79
101
    if (rrd_file == NULL) {
80
102
        rrd_free(&rrd);
81
103
        return (-1);
82
104
    }
83
105
 
84
 
    out_file = NULL;
85
 
    if (outname) {
86
 
        if (!(out_file = fopen(outname, "w"))) {
87
 
            return (-1);
88
 
        }
89
 
    } else {
90
 
        out_file = stdout;
91
 
    }
92
 
#ifdef HAVE_SETLOCALE
93
106
    old_locale = setlocale(LC_NUMERIC, "C");
94
 
#endif
95
 
    if (!opt_noheader) {
96
 
        fputs("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n", out_file);
97
 
        fputs
98
 
            ("<!DOCTYPE rrd SYSTEM \"http://oss.oetiker.ch/rrdtool/rrdtool.dtd\">\n",
99
 
             out_file);
 
107
 
 
108
 
 
109
    if (opt_header == 1) {
 
110
        CB_PUTS("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
 
111
        CB_PUTS("<!DOCTYPE rrd SYSTEM \"http://oss.oetiker.ch/rrdtool/rrdtool.dtd\">\n");
 
112
        CB_PUTS("<!-- Round Robin Database Dump -->\n");
 
113
        CB_PUTS("<rrd>\n");
 
114
    } else if (opt_header == 2) {
 
115
        CB_PUTS("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
 
116
        CB_PUTS("<!-- Round Robin Database Dump -->\n");
 
117
        CB_PUTS("<rrd xmlns=\"http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml\" "
 
118
                "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
 
119
        CB_PUTS("\txsi:schemaLocation=\"http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml "
 
120
                "http://oss.oetiker.ch/rrdtool/rrdtool-dump.xsd\">\n");
 
121
    } else {
 
122
        CB_PUTS("<!-- Round Robin Database Dump -->\n");
 
123
        CB_PUTS("<rrd>\n");
100
124
    }
101
 
    fputs("<!-- Round Robin Database Dump -->", out_file);
102
 
    fputs("<rrd>", out_file);
 
125
 
103
126
    if (atoi(rrd.stat_head->version) <= 3) {
104
 
        fprintf(out_file, "\t<version> %s </version>\n", RRD_VERSION3);
 
127
        CB_FMTS("\t<version>%s</version>\n", RRD_VERSION3);
105
128
    } else {
106
 
        fprintf(out_file, "\t<version> %s </version>\n", RRD_VERSION);
 
129
        CB_FMTS("\t<version>%s</version>\n", RRD_VERSION);
107
130
    }
108
 
    fprintf(out_file, "\t<step> %lu </step> <!-- Seconds -->\n",
109
 
            rrd.stat_head->pdp_step);
 
131
    
 
132
    CB_FMTS("\t<step>%lu</step> <!-- Seconds -->\n",
 
133
        rrd.stat_head->pdp_step);
 
134
 
110
135
#ifdef HAVE_STRFTIME
111
136
    localtime_r(&rrd.live_head->last_up, &tm);
112
 
    strftime(somestring, 200, "%Y-%m-%d %H:%M:%S %Z", &tm);
 
137
    strftime(somestring, 255, "%Y-%m-%d %H:%M:%S %Z", &tm);
113
138
#else
114
139
# error "Need strftime"
115
140
#endif
116
 
    fprintf(out_file, "\t<lastupdate> %lu </lastupdate> <!-- %s -->\n\n",
117
 
            (unsigned long) rrd.live_head->last_up, somestring);
 
141
    CB_FMTS("\t<lastupdate>%lld</lastupdate> <!-- %s -->\n\n",
 
142
        (long long) rrd.live_head->last_up, somestring);
118
143
    for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
119
 
        fprintf(out_file, "\t<ds>\n");
120
 
        fprintf(out_file, "\t\t<name> %s </name>\n", rrd.ds_def[i].ds_nam);
121
 
        fprintf(out_file, "\t\t<type> %s </type>\n", rrd.ds_def[i].dst);
 
144
        CB_PUTS("\t<ds>\n");
 
145
 
 
146
        CB_FMTS("\t\t<name> %s </name>\n", rrd.ds_def[i].ds_nam);
 
147
 
 
148
        CB_FMTS("\t\t<type> %s </type>\n", rrd.ds_def[i].dst);
 
149
 
122
150
        if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
123
 
            fprintf(out_file,
124
 
                    "\t\t<minimal_heartbeat> %lu </minimal_heartbeat>\n",
 
151
            CB_FMTS("\t\t<minimal_heartbeat>%lu</minimal_heartbeat>\n",
125
152
                    rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt);
 
153
 
126
154
            if (isnan(rrd.ds_def[i].par[DS_min_val].u_val)) {
127
 
                fprintf(out_file, "\t\t<min> NaN </min>\n");
 
155
                CB_PUTS("\t\t<min>NaN</min>\n");
128
156
            } else {
129
 
                fprintf(out_file, "\t\t<min> %0.10e </min>\n",
130
 
                        rrd.ds_def[i].par[DS_min_val].u_val);
 
157
                CB_FMTS("\t\t<min>%0.10e</min>\n",
 
158
                    rrd.ds_def[i].par[DS_min_val].u_val);
131
159
            }
 
160
            
132
161
            if (isnan(rrd.ds_def[i].par[DS_max_val].u_val)) {
133
 
                fprintf(out_file, "\t\t<max> NaN </max>\n");
 
162
                CB_PUTS("\t\t<max>NaN</max>\n");
134
163
            } else {
135
 
                fprintf(out_file, "\t\t<max> %0.10e </max>\n",
136
 
                        rrd.ds_def[i].par[DS_max_val].u_val);
 
164
                CB_FMTS("\t\t<max>%0.10e</max>\n",
 
165
                    rrd.ds_def[i].par[DS_max_val].u_val);
137
166
            }
138
167
        } else {        /* DST_CDEF */
139
168
            char     *str = NULL;
140
169
 
141
170
            rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),
142
 
                            rrd.ds_def, &str);
143
 
            fprintf(out_file, "\t\t<cdef> %s </cdef>\n", str);
 
171
                rrd.ds_def, &str);
 
172
 
 
173
            //Splitting into 3 writes to avoid allocating memory
 
174
            //This is better compared to snprintf as str may be of arbitrary size
 
175
            CB_PUTS("\t\t<cdef> ");
 
176
            CB_PUTS(str);
 
177
            CB_PUTS(" </cdef>\n");
 
178
 
144
179
            free(str);
145
180
        }
146
 
        fprintf(out_file, "\n\t\t<!-- PDP Status -->\n");
147
 
        fprintf(out_file, "\t\t<last_ds> %s </last_ds>\n",
148
 
                rrd.pdp_prep[i].last_ds);
 
181
 
 
182
        CB_PUTS("\n\t\t<!-- PDP Status -->\n");
 
183
        CB_FMTS("\t\t<last_ds>%s</last_ds>\n",
 
184
            rrd.pdp_prep[i].last_ds);
 
185
 
149
186
        if (isnan(rrd.pdp_prep[i].scratch[PDP_val].u_val)) {
150
 
            fprintf(out_file, "\t\t<value> NaN </value>\n");
 
187
            CB_PUTS("\t\t<value>NaN</value>\n");
151
188
        } else {
152
 
            fprintf(out_file, "\t\t<value> %0.10e </value>\n",
153
 
                    rrd.pdp_prep[i].scratch[PDP_val].u_val);
 
189
            CB_FMTS("\t\t<value>%0.10e</value>\n",
 
190
                rrd.pdp_prep[i].scratch[PDP_val].u_val);
154
191
        }
155
 
        fprintf(out_file, "\t\t<unknown_sec> %lu </unknown_sec>\n",
156
 
                rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
157
 
 
158
 
        fprintf(out_file, "\t</ds>\n\n");
 
192
 
 
193
        CB_FMTS("\t\t<unknown_sec> %lu </unknown_sec>\n",
 
194
            rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
 
195
 
 
196
        CB_PUTS("\t</ds>\n\n");
159
197
    }
160
198
 
161
 
    fputs("<!-- Round Robin Archives -->", out_file);
 
199
    CB_PUTS("\t<!-- Round Robin Archives -->\n");
162
200
 
163
201
    rra_base = rrd_file->header_len;
164
202
    rra_next = rra_base;
170
208
        rra_start = rra_next;
171
209
        rra_next += (rrd.stat_head->ds_cnt
172
210
                     * rrd.rra_def[i].row_cnt * sizeof(rrd_value_t));
173
 
        fprintf(out_file, "\t<rra>\n");
174
 
        fprintf(out_file, "\t\t<cf> %s </cf>\n", rrd.rra_def[i].cf_nam);
175
 
        fprintf(out_file,
176
 
                "\t\t<pdp_per_row> %lu </pdp_per_row> <!-- %lu seconds -->\n\n",
177
 
                rrd.rra_def[i].pdp_cnt,
178
 
                rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step);
 
211
 
 
212
        CB_PUTS("\t<rra>\n");
 
213
 
 
214
        CB_FMTS("\t\t<cf>%s</cf>\n", rrd.rra_def[i].cf_nam);
 
215
 
 
216
        CB_FMTS("\t\t<pdp_per_row>%lu</pdp_per_row> <!-- %lu seconds -->\n\n",
 
217
            rrd.rra_def[i].pdp_cnt, 
 
218
            rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step);
 
219
 
179
220
        /* support for RRA parameters */
180
 
        fprintf(out_file, "\t\t<params>\n");
 
221
        CB_PUTS("\t\t<params>\n");
 
222
 
181
223
        switch (cf_conv(rrd.rra_def[i].cf_nam)) {
182
224
        case CF_HWPREDICT:
183
225
        case CF_MHWPREDICT:
184
 
            fprintf(out_file, "\t\t<hw_alpha> %0.10e </hw_alpha>\n",
185
 
                    rrd.rra_def[i].par[RRA_hw_alpha].u_val);
186
 
            fprintf(out_file, "\t\t<hw_beta> %0.10e </hw_beta>\n",
187
 
                    rrd.rra_def[i].par[RRA_hw_beta].u_val);
188
 
            fprintf(out_file,
189
 
                    "\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
190
 
                    rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
 
226
            CB_FMTS("\t\t<hw_alpha>%0.10e</hw_alpha>\n",
 
227
                rrd.rra_def[i].par[RRA_hw_alpha].u_val);
 
228
 
 
229
            CB_FMTS("\t\t<hw_beta>%0.10e</hw_beta>\n",
 
230
                rrd.rra_def[i].par[RRA_hw_beta].u_val);
 
231
 
 
232
            CB_FMTS("\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
 
233
                rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
191
234
            break;
192
235
        case CF_SEASONAL:
193
236
        case CF_DEVSEASONAL:
194
 
            fprintf(out_file,
195
 
                    "\t\t<seasonal_gamma> %0.10e </seasonal_gamma>\n",
196
 
                    rrd.rra_def[i].par[RRA_seasonal_gamma].u_val);
197
 
            fprintf(out_file,
198
 
                    "\t\t<seasonal_smooth_idx> %lu </seasonal_smooth_idx>\n",
199
 
                    rrd.rra_def[i].par[RRA_seasonal_smooth_idx].u_cnt);
 
237
            CB_FMTS("\t\t<seasonal_gamma>%0.10e</seasonal_gamma>\n",
 
238
                rrd.rra_def[i].par[RRA_seasonal_gamma].u_val);
 
239
 
 
240
            CB_FMTS("\t\t<seasonal_smooth_idx>%lu</seasonal_smooth_idx>\n",
 
241
                rrd.rra_def[i].par[RRA_seasonal_smooth_idx].u_cnt);
 
242
 
200
243
            if (atoi(rrd.stat_head->version) >= 4) {
201
 
                fprintf(out_file,
202
 
                        "\t\t<smoothing_window> %0.10e </smoothing_window>\n",
203
 
                        rrd.rra_def[i].par[RRA_seasonal_smoothing_window].
204
 
                        u_val);
 
244
                CB_FMTS("\t\t<smoothing_window>%0.10e</smoothing_window>\n",
 
245
                    rrd.rra_def[i].par[RRA_seasonal_smoothing_window].u_val);
205
246
            }
206
 
            fprintf(out_file,
207
 
                    "\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
208
 
                    rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
 
247
 
 
248
            CB_FMTS("\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
 
249
                rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
209
250
            break;
210
251
        case CF_FAILURES:
211
 
            fprintf(out_file, "\t\t<delta_pos> %0.10e </delta_pos>\n",
212
 
                    rrd.rra_def[i].par[RRA_delta_pos].u_val);
213
 
            fprintf(out_file, "\t\t<delta_neg> %0.10e </delta_neg>\n",
214
 
                    rrd.rra_def[i].par[RRA_delta_neg].u_val);
215
 
            fprintf(out_file, "\t\t<window_len> %lu </window_len>\n",
216
 
                    rrd.rra_def[i].par[RRA_window_len].u_cnt);
217
 
            fprintf(out_file,
218
 
                    "\t\t<failure_threshold> %lu </failure_threshold>\n",
219
 
                    rrd.rra_def[i].par[RRA_failure_threshold].u_cnt);
 
252
            CB_FMTS("\t\t<delta_pos>%0.10e</delta_pos>\n",
 
253
                rrd.rra_def[i].par[RRA_delta_pos].u_val);
 
254
 
 
255
            CB_FMTS("\t\t<delta_neg>%0.10e</delta_neg>\n",
 
256
                rrd.rra_def[i].par[RRA_delta_neg].u_val);
 
257
 
 
258
            CB_FMTS("\t\t<window_len>%lu</window_len>\n",
 
259
                rrd.rra_def[i].par[RRA_window_len].u_cnt);
 
260
 
 
261
            CB_FMTS("\t\t<failure_threshold>%lu</failure_threshold>\n",
 
262
                rrd.rra_def[i].par[RRA_failure_threshold].u_cnt);
 
263
 
220
264
            /* fall thru */
221
265
        case CF_DEVPREDICT:
222
 
            fprintf(out_file,
223
 
                    "\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
224
 
                    rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
 
266
            CB_FMTS("\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
 
267
                rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
225
268
            break;
226
269
        case CF_AVERAGE:
227
270
        case CF_MAXIMUM:
228
271
        case CF_MINIMUM:
229
272
        case CF_LAST:
230
273
        default:
231
 
            fprintf(out_file, "\t\t<xff> %0.10e </xff>\n",
232
 
                    rrd.rra_def[i].par[RRA_cdp_xff_val].u_val);
 
274
            CB_FMTS("\t\t<xff>%0.10e</xff>\n",
 
275
                rrd.rra_def[i].par[RRA_cdp_xff_val].u_val);
233
276
            break;
234
277
        }
235
 
        fprintf(out_file, "\t\t</params>\n");
236
 
        fprintf(out_file, "\t\t<cdp_prep>\n");
 
278
 
 
279
        CB_PUTS("\t\t</params>\n");
 
280
        CB_PUTS("\t\t<cdp_prep>\n");
 
281
 
237
282
        for (ii = 0; ii < rrd.stat_head->ds_cnt; ii++) {
238
283
            unsigned long ivalue;
239
284
 
240
 
            fprintf(out_file, "\t\t\t<ds>\n");
 
285
            CB_PUTS("\t\t\t<ds>\n");
241
286
            /* support for exporting all CDP parameters */
242
287
            /* parameters common to all CFs */
243
288
            /* primary_val and secondary_val do not need to be saved between updates
244
289
             * so strictly speaking they could be omitted.
245
290
             * However, they can be useful for diagnostic purposes, so are included here. */
246
 
            value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt
247
 
                                 + ii].scratch[CDP_primary_val].u_val;
248
 
            if (isnan(value)) {
249
 
                fprintf(out_file,
250
 
                        "\t\t\t<primary_value> NaN </primary_value>\n");
251
 
            } else {
252
 
                fprintf(out_file,
253
 
                        "\t\t\t<primary_value> %0.10e </primary_value>\n",
254
 
                        value);
255
 
            }
256
 
            value =
257
 
                rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
258
 
                             ii].scratch[CDP_secondary_val].u_val;
259
 
            if (isnan(value)) {
260
 
                fprintf(out_file,
261
 
                        "\t\t\t<secondary_value> NaN </secondary_value>\n");
262
 
            } else {
263
 
                fprintf(out_file,
264
 
                        "\t\t\t<secondary_value> %0.10e </secondary_value>\n",
265
 
                        value);
266
 
            }
 
291
            value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
292
                scratch[CDP_primary_val].u_val;
 
293
            if (isnan(value)) {
 
294
                CB_PUTS("\t\t\t<primary_value>NaN</primary_value>\n");
 
295
            } else {
 
296
                CB_FMTS("\t\t\t<primary_value>%0.10e</primary_value>\n", value);
 
297
            }
 
298
 
 
299
            value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
300
                scratch[CDP_secondary_val].u_val;
 
301
            if (isnan(value)) {
 
302
                CB_PUTS("\t\t\t<secondary_value>NaN</secondary_value>\n");
 
303
            } else {
 
304
                CB_FMTS("\t\t\t<secondary_value>%0.10e</secondary_value>\n", value);
 
305
            }
 
306
 
267
307
            switch (cf_conv(rrd.rra_def[i].cf_nam)) {
268
308
            case CF_HWPREDICT:
269
309
            case CF_MHWPREDICT:
270
 
                value =
271
 
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
272
 
                                 ii].scratch[CDP_hw_intercept].u_val;
273
 
                if (isnan(value)) {
274
 
                    fprintf(out_file, "\t\t\t<intercept> NaN </intercept>\n");
275
 
                } else {
276
 
                    fprintf(out_file,
277
 
                            "\t\t\t<intercept> %0.10e </intercept>\n", value);
278
 
                }
279
 
                value =
280
 
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
281
 
                                 ii].scratch[CDP_hw_last_intercept].u_val;
282
 
                if (isnan(value)) {
283
 
                    fprintf(out_file,
284
 
                            "\t\t\t<last_intercept> NaN </last_intercept>\n");
285
 
                } else {
286
 
                    fprintf(out_file,
287
 
                            "\t\t\t<last_intercept> %0.10e </last_intercept>\n",
288
 
                            value);
289
 
                }
290
 
                value =
291
 
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
292
 
                                 ii].scratch[CDP_hw_slope].u_val;
293
 
                if (isnan(value)) {
294
 
                    fprintf(out_file, "\t\t\t<slope> NaN </slope>\n");
295
 
                } else {
296
 
                    fprintf(out_file, "\t\t\t<slope> %0.10e </slope>\n",
297
 
                            value);
298
 
                }
299
 
                value =
300
 
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
301
 
                                 ii].scratch[CDP_hw_last_slope].u_val;
302
 
                if (isnan(value)) {
303
 
                    fprintf(out_file,
304
 
                            "\t\t\t<last_slope> NaN </last_slope>\n");
305
 
                } else {
306
 
                    fprintf(out_file,
307
 
                            "\t\t\t<last_slope> %0.10e </last_slope>\n",
308
 
                            value);
309
 
                }
310
 
                ivalue =
311
 
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
312
 
                                 ii].scratch[CDP_null_count].u_cnt;
313
 
                fprintf(out_file, "\t\t\t<nan_count> %lu </nan_count>\n",
314
 
                        ivalue);
315
 
                ivalue =
316
 
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
317
 
                                 ii].scratch[CDP_last_null_count].u_cnt;
318
 
                fprintf(out_file,
319
 
                        "\t\t\t<last_nan_count> %lu </last_nan_count>\n",
320
 
                        ivalue);
 
310
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
311
                    scratch[CDP_hw_intercept].u_val;
 
312
                if (isnan(value)) {
 
313
                    CB_PUTS("\t\t\t<intercept>NaN</intercept>\n");
 
314
                } else {
 
315
                    CB_FMTS("\t\t\t<intercept>%0.10e</intercept>\n", value);
 
316
                }
 
317
 
 
318
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
319
                    scratch[CDP_hw_last_intercept].u_val;
 
320
                if (isnan(value)) {
 
321
                    CB_PUTS("\t\t\t<last_intercept>NaN</last_intercept>\n");
 
322
                } else {
 
323
                    CB_FMTS("\t\t\t<last_intercept>%0.10e</last_intercept>\n", value);
 
324
                }
 
325
 
 
326
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
327
                    scratch[CDP_hw_slope].u_val;
 
328
                if (isnan(value)) {
 
329
                    CB_PUTS("\t\t\t<slope>NaN</slope>\n");
 
330
                } else {
 
331
                    CB_FMTS("\t\t\t<slope>%0.10e</slope>\n", value);
 
332
                }
 
333
 
 
334
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
335
                    scratch[CDP_hw_last_slope].u_val;
 
336
                if (isnan(value)) {
 
337
                    CB_PUTS("\t\t\t<last_slope>NaN</last_slope>\n");
 
338
                } else {
 
339
                    CB_FMTS("\t\t\t<last_slope>%0.10e</last_slope>\n", value);
 
340
                }
 
341
 
 
342
                ivalue = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
343
                    scratch[CDP_null_count].u_cnt;
 
344
                CB_FMTS("\t\t\t<nan_count>%lu</nan_count>\n", ivalue);
 
345
 
 
346
                ivalue = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
347
                    scratch[CDP_last_null_count].u_cnt;
 
348
                CB_FMTS("\t\t\t<last_nan_count>%lu</last_nan_count>\n", ivalue);
321
349
                break;
322
350
            case CF_SEASONAL:
323
351
            case CF_DEVSEASONAL:
324
 
                value =
325
 
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
326
 
                                 ii].scratch[CDP_hw_seasonal].u_val;
327
 
                if (isnan(value)) {
328
 
                    fprintf(out_file, "\t\t\t<seasonal> NaN </seasonal>\n");
329
 
                } else {
330
 
                    fprintf(out_file, "\t\t\t<seasonal> %0.10e </seasonal>\n",
331
 
                            value);
332
 
                }
333
 
                value =
334
 
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
335
 
                                 ii].scratch[CDP_hw_last_seasonal].u_val;
336
 
                if (isnan(value)) {
337
 
                    fprintf(out_file,
338
 
                            "\t\t\t<last_seasonal> NaN </last_seasonal>\n");
339
 
                } else {
340
 
                    fprintf(out_file,
341
 
                            "\t\t\t<last_seasonal> %0.10e </last_seasonal>\n",
342
 
                            value);
343
 
                }
344
 
                ivalue =
345
 
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
346
 
                                 ii].scratch[CDP_init_seasonal].u_cnt;
347
 
                fprintf(out_file, "\t\t\t<init_flag> %lu </init_flag>\n",
348
 
                        ivalue);
 
352
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
353
                    scratch[CDP_hw_seasonal].u_val;
 
354
                if (isnan(value)) {
 
355
                    CB_PUTS("\t\t\t<seasonal>NaN</seasonal>\n");
 
356
                } else {
 
357
                    CB_FMTS("\t\t\t<seasonal>%0.10e</seasonal>\n", value);
 
358
                }
 
359
 
 
360
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
361
                    scratch[CDP_hw_last_seasonal].u_val;
 
362
                if (isnan(value)) {
 
363
                    CB_PUTS("\t\t\t<last_seasonal>NaN</last_seasonal>\n");
 
364
                } else {
 
365
                    CB_FMTS("\t\t\t<last_seasonal>%0.10e</last_seasonal>\n", value);
 
366
                }
 
367
 
 
368
                ivalue = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
369
                    scratch[CDP_init_seasonal].u_cnt;
 
370
                CB_FMTS("\t\t\t<init_flag>%lu</init_flag>\n", ivalue);
349
371
                break;
350
372
            case CF_DEVPREDICT:
351
373
                break;
352
374
            case CF_FAILURES:
353
375
            {
354
376
                unsigned short vidx;
355
 
                char     *violations_array = (char *) ((void *)
356
 
                                                       rrd.cdp_prep[i *
357
 
                                                                    rrd.
358
 
                                                                    stat_head->
359
 
                                                                    ds_cnt +
360
 
                                                                    ii].
361
 
                                                       scratch);
362
 
                fprintf(out_file, "\t\t\t<history> ");
 
377
                char *violations_array = (char *) ((void *)
 
378
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].scratch);
 
379
                CB_PUTS("\t\t\t<history>");
363
380
                for (vidx = 0;
364
 
                     vidx < rrd.rra_def[i].par[RRA_window_len].u_cnt;
365
 
                     ++vidx) {
366
 
                    fprintf(out_file, "%d", violations_array[vidx]);
 
381
                    vidx < rrd.rra_def[i].par[RRA_window_len].u_cnt;
 
382
                    ++vidx) {
 
383
                    CB_FMTS("%d", violations_array[vidx]);
367
384
                }
368
 
                fprintf(out_file, " </history>\n");
 
385
                CB_PUTS("</history>\n");
369
386
            }
370
387
                break;
371
388
            case CF_AVERAGE:
373
390
            case CF_MINIMUM:
374
391
            case CF_LAST:
375
392
            default:
376
 
                value =
377
 
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
378
 
                                 ii].scratch[CDP_val].u_val;
 
393
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].scratch[CDP_val].u_val;
379
394
                if (isnan(value)) {
380
 
                    fprintf(out_file, "\t\t\t<value> NaN </value>\n");
 
395
                    CB_PUTS("\t\t\t<value>NaN</value>\n");
381
396
                } else {
382
 
                    fprintf(out_file, "\t\t\t<value> %0.10e </value>\n",
383
 
                            value);
 
397
                    CB_FMTS("\t\t\t<value>%0.10e</value>\n", value);
384
398
                }
385
 
                fprintf(out_file,
386
 
                        "\t\t\t<unknown_datapoints> %lu </unknown_datapoints>\n",
387
 
                        rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
388
 
                                     ii].scratch[CDP_unkn_pdp_cnt].u_cnt);
 
399
 
 
400
                CB_FMTS("\t\t\t<unknown_datapoints>%lu</unknown_datapoints>\n",
 
401
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
 
402
                        scratch[CDP_unkn_pdp_cnt].u_cnt);
389
403
                break;
390
404
            }
391
 
            fprintf(out_file, "\t\t\t</ds>\n");
 
405
            CB_PUTS("\t\t\t</ds>\n");
392
406
        }
393
 
        fprintf(out_file, "\t\t</cdp_prep>\n");
 
407
        CB_PUTS("\t\t</cdp_prep>\n");
394
408
 
395
 
        fprintf(out_file, "\t\t<database>\n");
 
409
        CB_PUTS("\t\t<database>\n");
396
410
        rrd_seek(rrd_file, (rra_start + (rrd.rra_ptr[i].cur_row + 1)
397
411
                            * rrd.stat_head->ds_cnt
398
412
                            * sizeof(rrd_value_t)), SEEK_SET);
399
 
        timer = - (long)(rrd.rra_def[i].row_cnt - 1);
 
413
        timer = -(long)(rrd.rra_def[i].row_cnt - 1);
400
414
        ii = rrd.rra_ptr[i].cur_row;
401
415
        for (ix = 0; ix < rrd.rra_def[i].row_cnt; ix++) {
402
416
            ii++;
412
426
            timer++;
413
427
#if HAVE_STRFTIME
414
428
            localtime_r(&now, &tm);
415
 
            strftime(somestring, 200, "%Y-%m-%d %H:%M:%S %Z", &tm);
 
429
            strftime(somestring, 255, "%Y-%m-%d %H:%M:%S %Z", &tm);
416
430
#else
417
431
# error "Need strftime"
418
432
#endif
419
 
            fprintf(out_file, "\t\t\t<!-- %s / %d --> <row>", somestring,
420
 
                    (int) now);
 
433
            CB_FMTS("\t\t\t<!-- %s / %lld --> <row>",  somestring, (long long) now);
421
434
            for (iii = 0; iii < rrd.stat_head->ds_cnt; iii++) {
422
435
                rrd_read(rrd_file, &my_cdp, sizeof(rrd_value_t) * 1);
423
436
                if (isnan(my_cdp)) {
424
 
                    fprintf(out_file, "<v> NaN </v>");
 
437
                    CB_PUTS("<v>NaN</v>");
425
438
                } else {
426
 
                    fprintf(out_file, "<v> %0.10e </v>", my_cdp);
427
 
                };
 
439
                    CB_FMTS("<v>%0.10e</v>", my_cdp);
 
440
                }
428
441
            }
429
 
            fprintf(out_file, "</row>\n");
 
442
            CB_PUTS("</row>\n");
430
443
        }
431
 
        fprintf(out_file, "\t\t</database>\n\t</rra>\n");
432
 
 
 
444
        CB_PUTS("\t\t</database>\n\t</rra>\n");
433
445
    }
434
 
    fprintf(out_file, "</rrd>\n");
 
446
 
 
447
    CB_PUTS("</rrd>\n");
 
448
 
435
449
    rrd_free(&rrd);
 
450
 
 
451
    setlocale(LC_NUMERIC, old_locale);
 
452
 
 
453
    return rrd_close(rrd_file);
 
454
 
 
455
//Undefining the previously defined shortcuts
 
456
//See start of this function
 
457
#undef CB_PUTS
 
458
#undef CB_FMTS
 
459
//End of macro undefining
 
460
 
 
461
}
 
462
 
 
463
size_t rrd_dump_opt_cb_fileout(
 
464
    const void *data,
 
465
    size_t len,
 
466
    void *user)
 
467
{
 
468
    return fwrite(data, 1, len, (FILE *)user);
 
469
}
 
470
 
 
471
int rrd_dump_opt_r(
 
472
    const char *filename,
 
473
    char *outname,
 
474
    int opt_noheader)
 
475
{
 
476
    FILE     *out_file;
 
477
    int       res;
 
478
 
 
479
    out_file = NULL;
 
480
    if (outname) {
 
481
        if (!(out_file = fopen(outname, "w"))) {
 
482
            return (-1);
 
483
        }
 
484
    } else {
 
485
        out_file = stdout;
 
486
    }
 
487
 
 
488
    res = rrd_dump_cb_r(filename, opt_noheader, rrd_dump_opt_cb_fileout, (void *)out_file);
 
489
 
436
490
    if (out_file != stdout) {
437
491
        fclose(out_file);
438
492
    }
439
 
#ifdef HAVE_SETLOCALE
440
 
    setlocale(LC_NUMERIC, old_locale);
441
 
#endif
442
 
    return rrd_close(rrd_file);
 
493
 
 
494
    return res;
443
495
}
444
496
 
445
497
/* backward compatibility with 1.2.x */
455
507
    char **argv)
456
508
{
457
509
    int       rc;
458
 
    int       opt_noheader = 0;
 
510
    /** 
 
511
     * 0 = no header
 
512
     * 1 = dtd header
 
513
     * 2 = xsd header
 
514
     */
 
515
    int       opt_header = 1;
 
516
    char     *opt_daemon = NULL;
459
517
 
460
518
    /* init rrd clean */
461
519
 
462
520
    optind = 0;
463
521
    opterr = 0;         /* initialize getopt */
464
522
 
465
 
    while (42) {
 
523
    while (42) {/* ha ha */
466
524
        int       opt;
467
525
        int       option_index = 0;
468
526
        static struct option long_options[] = {
 
527
            {"daemon", required_argument, 0, 'd'},
 
528
            {"header", required_argument, 0, 'h'},
469
529
            {"no-header", no_argument, 0, 'n'},
470
530
            {0, 0, 0, 0}
471
531
        };
472
532
 
473
 
        opt = getopt_long(argc, argv, "n", long_options, &option_index);
 
533
        opt = getopt_long(argc, argv, "d:h:n", long_options, &option_index);
474
534
 
475
535
        if (opt == EOF)
476
536
            break;
477
537
 
478
538
        switch (opt) {
 
539
        case 'd':
 
540
            if (opt_daemon != NULL)
 
541
                    free (opt_daemon);
 
542
            opt_daemon = strdup (optarg);
 
543
            if (opt_daemon == NULL)
 
544
            {
 
545
                rrd_set_error ("strdup failed.");
 
546
                return (-1);
 
547
            }
 
548
            break;
 
549
 
479
550
        case 'n':
480
 
            opt_noheader = 1;
481
 
            break;
 
551
           opt_header = 0;
 
552
           break;
 
553
 
 
554
        case 'h':
 
555
           if (strcmp(optarg, "dtd") == 0) {
 
556
                opt_header = 1;
 
557
           } else if (strcmp(optarg, "xsd") == 0) {
 
558
                opt_header = 2;
 
559
           } else if (strcmp(optarg, "none") == 0) {
 
560
                opt_header = 0;
 
561
           }
 
562
           break;
482
563
 
483
564
        default:
484
 
            rrd_set_error("usage rrdtool %s [--no-header|-n] "
 
565
            rrd_set_error("usage rrdtool %s [--header|-h {none,xsd,dtd}] [--no-header]"
485
566
                          "file.rrd [file.xml]", argv[0]);
486
567
            return (-1);
487
568
            break;
489
570
    }                   /* while (42) */
490
571
 
491
572
    if ((argc - optind) < 1 || (argc - optind) > 2) {
492
 
        rrd_set_error("usage rrdtool %s [--no-header|-n] "
 
573
        rrd_set_error("usage rrdtool %s [--header|-h {none,xsd,dtd}] [--no-header]"
493
574
                      "file.rrd [file.xml]", argv[0]);
494
575
        return (-1);
495
576
    }
496
577
 
 
578
    rc = rrdc_flush_if_daemon(opt_daemon, argv[optind]);
 
579
    if (opt_daemon) free(opt_daemon);
 
580
    if (rc) return (rc);
 
581
 
497
582
    if ((argc - optind) == 2) {
498
 
        rc = rrd_dump_opt_r(argv[optind], argv[optind + 1], opt_noheader);
 
583
        rc = rrd_dump_opt_r(argv[optind], argv[optind + 1], opt_header);
499
584
    } else {
500
 
        rc = rrd_dump_opt_r(argv[optind], NULL, opt_noheader);
 
585
        rc = rrd_dump_opt_r(argv[optind], NULL, opt_header);
501
586
    }
502
587
 
503
588
    return rc;