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

« back to all changes in this revision

Viewing changes to src/rrd_restore.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
3
 
 * This file:     Copyright 2008 Florian octo Forster
4
 
 * Distributed under the GPL
5
 
 *****************************************************************************
6
 
 * rrd_restore.c   Contains logic to parse XML input and create an RRD file
7
 
 *****************************************************************************
8
 
 * $Id: rrd_restore.c 1801 2009-05-19 13:45:05Z oetiker $
 
2
 * RRDtool 1.4.3  Copyright by Tobi Oetiker, 1997-2010                    
 
3
 *****************************************************************************
 
4
 * rrd_restore.c  Contains logic to parse XML input and create an RRD file
 
5
 * This file:
 
6
 * Copyright (C) 2008  Florian octo Forster  (original libxml2 code)
 
7
 * Copyright (C) 2008,2009 Tobias Oetiker
 
8
 *****************************************************************************
 
9
 * $Id: rrd_restore.c 2042 2010-03-22 16:05:55Z oetiker $
9
10
 *************************************************************************** */
10
11
 
11
 
/*
12
 
 * This program is free software; you can redistribute it and / or modify it
13
 
 * under the terms of the GNU General Public License as published by the Free
14
 
 * Software Foundation; either version 2 of the License, or (t your option)
15
 
 * any later version.
16
 
 * 
17
 
 * This program is distributed in the hope that it will be useful, but WITHOUT
18
 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
 
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
20
 
 * more details.
21
 
 *
22
 
 * You should have received a copy of the GNU General Public License along
23
 
 * with this program; if not, write to the Free Software Foundation, Inc.,
24
 
 * 51 Franklin St, Fifth Floor, Boston, MA 02110 - 1301 USA
25
 
 *
26
 
 * Authors:
27
 
 *   Florian octo Forster <octo at verplant.org>
28
 
 **/
 
12
#include "rrd_tool.h"
 
13
#include "rrd_rpncalc.h"
29
14
 
 
15
#include <stdio.h>
30
16
#include <stdlib.h>
31
 
#include <stdio.h>
32
17
#include <string.h>
33
 
#include <ctype.h>
 
18
#include <libxml/parser.h>
 
19
#include <libxml/xmlreader.h>
 
20
#include <locale.h>
 
21
 
 
22
#ifndef WIN32
 
23
#       include <unistd.h>     /* for off_t */
 
24
#else
 
25
        typedef size_t ssize_t;
 
26
        typedef long off_t;
 
27
#endif 
 
28
 
34
29
#include <fcntl.h>
35
 
 
36
 
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
37
 
#include <math.h>
 
30
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
38
31
# include <io.h>
39
32
# define open _open
40
33
# define close _close
41
 
#else
42
 
# include <unistd.h>
43
34
#endif
44
35
 
45
 
#include <libxml/parser.h>
46
 
#include "rrd_tool.h"
47
 
#include "rrd_rpncalc.h"
 
36
 
48
37
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof ((a)[0]))
 
38
 
49
39
static int opt_range_check = 0;
50
40
static int opt_force_overwrite = 0;
51
41
 
52
42
/*
53
 
 * Auxiliary functions
 
43
 * Helpers
54
44
 */
55
 
static int get_string_from_node(
56
 
    xmlDoc * doc,
57
 
    xmlNode * node,
58
 
    char *buffer,
59
 
    size_t buffer_size)
60
 
{
61
 
    xmlChar  *temp0;
62
 
    char     *begin_ptr;
63
 
    char     *end_ptr;
64
 
 
65
 
    temp0 = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
66
 
    if (temp0 == NULL) {
67
 
        rrd_set_error("get_string_from_node: xmlNodeListGetString failed.");
68
 
        return (-1);
69
 
    }
70
 
 
71
 
    begin_ptr = (char *) temp0;
72
 
    while ((begin_ptr[0] != 0) && (isspace(begin_ptr[0])))
73
 
        begin_ptr++;
74
 
 
75
 
    if (begin_ptr[0] == 0) {
76
 
        xmlFree(temp0);
77
 
        buffer[0] = 0;
78
 
        return (0);
79
 
    }
80
 
 
81
 
    end_ptr = begin_ptr;
82
 
    while ((end_ptr[0] != 0) && (!isspace(end_ptr[0])))
83
 
        end_ptr++;
84
 
    end_ptr[0] = 0;
85
 
 
86
 
    strncpy(buffer, begin_ptr, buffer_size);
87
 
    buffer[buffer_size - 1] = 0;
88
 
 
89
 
    xmlFree(temp0);
90
 
 
91
 
    return (0);
92
 
}                       /* int get_string_from_node */
93
 
 
94
 
static int get_long_from_node(
95
 
    xmlDoc * doc,
96
 
    xmlNode * node,
97
 
    long *value)
98
 
{
99
 
    long       temp;
100
 
    char     *str_ptr;
101
 
    char     *end_ptr;
102
 
 
103
 
    str_ptr = (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
104
 
    if (str_ptr == NULL) {
105
 
        rrd_set_error("get_long_from_node: xmlNodeListGetString failed.");
106
 
        return (-1);
107
 
    }
108
 
 
109
 
    end_ptr = NULL;
110
 
    temp = strtol(str_ptr, &end_ptr, 0);
111
 
    xmlFree(str_ptr);
112
 
 
113
 
    if (str_ptr == end_ptr) {
114
 
        rrd_set_error("get_long_from_node: Cannot parse buffer as long: %s",
115
 
                      str_ptr);
116
 
        return (-1);
117
 
    }
118
 
 
119
 
    *value = temp;
120
 
 
121
 
    return (0);
122
 
}                       /* int get_long_from_node */
123
 
 
124
 
static int get_ulong_from_node(
125
 
    xmlDoc * doc,
126
 
    xmlNode * node,
 
45
 
 
46
/* skip all but tags. complain if we do not get the right tag */
 
47
/* dept -1 causes depth to be ignored */
 
48
static xmlChar* get_xml_element (
 
49
    xmlTextReaderPtr reader
 
50
    )
 
51
{
 
52
    while(xmlTextReaderRead(reader)){
 
53
        int type;
 
54
        xmlChar *name;
 
55
        type = xmlTextReaderNodeType(reader);
 
56
        if (type == XML_READER_TYPE_TEXT){
 
57
            xmlChar *value;
 
58
            value = xmlTextReaderValue(reader);
 
59
            rrd_set_error("line %d: expected element but found text '%s'",
 
60
                          xmlTextReaderGetParserLineNumber(reader),value);
 
61
            xmlFree(value);
 
62
            return NULL;
 
63
        }
 
64
        /* skip all other non-elements */
 
65
        if (type != XML_READER_TYPE_ELEMENT && type != XML_READER_TYPE_END_ELEMENT)
 
66
            continue;
 
67
 
 
68
        name = xmlTextReaderName(reader);
 
69
        if (type == XML_READER_TYPE_END_ELEMENT){
 
70
            xmlChar *temp;
 
71
            xmlChar *temp2;            
 
72
            temp = (xmlChar*)sprintf_alloc("/%s",name);
 
73
            temp2 = xmlStrdup(temp);
 
74
            free(temp);
 
75
            xmlFree(name);            
 
76
            return temp2;            
 
77
        }
 
78
        /* all seems well, return the happy news */
 
79
        return name;
 
80
    }
 
81
    rrd_set_error("the xml ended while we were looking for an element");
 
82
    return NULL;
 
83
} /* get_xml_element */
 
84
 
 
85
static void local_rrd_free (rrd_t *rrd)
 
86
{    
 
87
    free(rrd->live_head);
 
88
    free(rrd->stat_head);
 
89
    free(rrd->ds_def);
 
90
    free(rrd->rra_def); 
 
91
    free(rrd->rra_ptr);
 
92
    free(rrd->pdp_prep);
 
93
    free(rrd->cdp_prep);
 
94
    free(rrd->rrd_value);
 
95
    free(rrd);
 
96
}
 
97
 
 
98
 
 
99
static int expect_element (
 
100
    xmlTextReaderPtr reader,
 
101
    char *exp_name)
 
102
{
 
103
    xmlChar *name;
 
104
    name = get_xml_element(reader);
 
105
    if (!name)
 
106
        return -1;    
 
107
    if (xmlStrcasecmp(name,(xmlChar *)exp_name) != 0){
 
108
        rrd_set_error("line %d: expected <%s> element but found <%s>",
 
109
                      xmlTextReaderGetParserLineNumber(reader),name,exp_name);
 
110
        xmlFree(name);            
 
111
        return -1;            
 
112
    }
 
113
    xmlFree(name);    
 
114
    return 0;    
 
115
} /* expect_element */
 
116
 
 
117
static int expect_element_end (
 
118
    xmlTextReaderPtr reader,
 
119
    char *exp_name)
 
120
{
 
121
    xmlChar *name;
 
122
    /* maybe we are already on the end element ... lets see */
 
123
    if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT){
 
124
         xmlChar *temp;
 
125
         xmlChar *temp2;            
 
126
         temp = xmlTextReaderName(reader);
 
127
         temp2 = (xmlChar*)sprintf_alloc("/%s", temp);
 
128
         name = xmlStrdup(temp2);
 
129
         xmlFree(temp);
 
130
         free(temp2);            
 
131
    } else {     
 
132
         name = get_xml_element(reader);
 
133
    }
 
134
 
 
135
    if (name == NULL)
 
136
        return -1;    
 
137
    if (xmlStrcasecmp(name+1,(xmlChar *)exp_name) != 0 || name[0] != '/'){
 
138
        rrd_set_error("line %d: expected </%s> end element but found <%s>",
 
139
                      xmlTextReaderGetParserLineNumber(reader),exp_name,name);
 
140
        xmlFree(name);            
 
141
        return -1;            
 
142
    }
 
143
    xmlFree(name);    
 
144
    return 0;    
 
145
} /* expect_element_end */
 
146
 
 
147
 
 
148
static xmlChar* get_xml_text (
 
149
    xmlTextReaderPtr reader
 
150
    )
 
151
{
 
152
    while(xmlTextReaderRead(reader)){
 
153
        xmlChar  *ret;    
 
154
        xmlChar  *text;
 
155
        xmlChar  *begin_ptr;
 
156
        xmlChar  *end_ptr;
 
157
        int type;        
 
158
        type = xmlTextReaderNodeType(reader);
 
159
        if (type == XML_READER_TYPE_ELEMENT){
 
160
            xmlChar *name;
 
161
            name = xmlTextReaderName(reader);
 
162
            rrd_set_error("line %d: expected a value but found a <%s> element",
 
163
                          xmlTextReaderGetParserLineNumber(reader),
 
164
                          name);
 
165
            xmlFree(name);            
 
166
            return NULL;            
 
167
        }
 
168
 
 
169
        /* trying to read text from <a></a> we end up here
 
170
           lets return an empty string insead. This is a tad optimistic
 
171
           since we do not check if it is actually </a> and not </b>
 
172
           we got, but first we do not know if we expect </a> and second
 
173
           we the whole implementation is on the optimistic side. */
 
174
        if (type == XML_READER_TYPE_END_ELEMENT){
 
175
            return  xmlStrdup(BAD_CAST "");
 
176
        }        
 
177
 
 
178
        /* skip all other non-text */
 
179
        if (type != XML_READER_TYPE_TEXT)
 
180
            continue;
 
181
        
 
182
        text = xmlTextReaderValue(reader);
 
183
 
 
184
        begin_ptr = text;
 
185
        while ((begin_ptr[0] != 0) && (isspace(begin_ptr[0])))
 
186
            begin_ptr++;
 
187
        if (begin_ptr[0] == 0) {
 
188
            xmlFree(text);
 
189
            return xmlStrdup(BAD_CAST "");
 
190
        }        
 
191
        end_ptr = begin_ptr;
 
192
        while ((end_ptr[0] != 0) && (!isspace(end_ptr[0])))
 
193
            end_ptr++;
 
194
        end_ptr[0] = 0;
 
195
        
 
196
        ret = xmlStrdup(begin_ptr);
 
197
        xmlFree(text);
 
198
        return ret;
 
199
    }
 
200
    rrd_set_error("file ended while looking for text");
 
201
    return NULL;
 
202
}  /* get_xml_text */ 
 
203
 
 
204
 
 
205
static int get_xml_string(
 
206
    xmlTextReaderPtr reader,
 
207
    char *value,
 
208
    int max_len)
 
209
{
 
210
    xmlChar *str;
 
211
    str = get_xml_text(reader);
 
212
    if (str != NULL){
 
213
        strncpy(value,(char *)str,max_len);
 
214
        xmlFree(str);
 
215
        return 0;        
 
216
    }
 
217
    else
 
218
        return -1;    
 
219
}
 
220
 
 
221
 
 
222
static int get_xml_time_t(
 
223
    xmlTextReaderPtr reader,
 
224
    time_t *value)
 
225
{    
 
226
    xmlChar *text;
 
227
    time_t temp;    
 
228
    if ((text = get_xml_text(reader)) != NULL){
 
229
        errno = 0;        
 
230
#ifdef TIME_T_IS_32BIT
 
231
        temp = strtol((char *)text,NULL, 0);
 
232
#else
 
233
#ifdef TIME_T_IS_64BIT
 
234
        temp = strtoll((char *)text,NULL, 0);        
 
235
#else
 
236
        if (sizeof(time_t) == 4){
 
237
            temp = strtol((char *)text,NULL, 0);
 
238
        } else {
 
239
            temp = strtoll((char *)text,NULL, 0);
 
240
        }
 
241
#endif
 
242
#endif    
 
243
        if (errno>0){
 
244
            rrd_set_error("ling %d: get_xml_time_t from '%s' %s",
 
245
                          xmlTextReaderGetParserLineNumber(reader),
 
246
                          text,rrd_strerror(errno));
 
247
            xmlFree(text);            
 
248
            return -1;
 
249
        }
 
250
        xmlFree(text);            
 
251
        *value = temp;
 
252
        return 0;
 
253
    }
 
254
    return -1;
 
255
} /* get_xml_time_t */
 
256
 
 
257
static int get_xml_ulong(
 
258
    xmlTextReaderPtr reader,
127
259
    unsigned long *value)
128
260
{
129
 
    unsigned long       temp;
130
 
    char     *str_ptr;
131
 
    char     *end_ptr;
132
 
 
133
 
    str_ptr = (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
134
 
    if (str_ptr == NULL) {
135
 
        rrd_set_error("get_ulong_from_node: xmlNodeListGetString failed.");
136
 
        return (-1);
137
 
    }
138
 
 
139
 
    end_ptr = NULL;
140
 
    temp = strtoul(str_ptr, &end_ptr, 0);
141
 
    xmlFree(str_ptr);
142
 
 
143
 
    if (str_ptr == end_ptr) {
144
 
        rrd_set_error("get_ulong_from_node: Cannot parse buffer as unsigned long: %s",
145
 
                      str_ptr);
146
 
        return (-1);
147
 
    }
148
 
 
149
 
    *value = temp;
150
 
 
151
 
    return (0);
152
 
}                       /* int get_ulong_from_node */
153
 
 
154
 
static int get_double_from_node(
155
 
    xmlDoc * doc,
156
 
    xmlNode * node,
 
261
    
 
262
    xmlChar *text;
 
263
    unsigned long temp;    
 
264
    if ((text = get_xml_text(reader)) != NULL){
 
265
        errno = 0;        
 
266
        temp = strtoul((char *)text,NULL, 0);        
 
267
        if (errno>0){
 
268
            rrd_set_error("ling %d: get_xml_ulong from '%s' %s",
 
269
                          xmlTextReaderGetParserLineNumber(reader),
 
270
                          text,rrd_strerror(errno));
 
271
            xmlFree(text);            
 
272
            return -1;
 
273
        }
 
274
        xmlFree(text);
 
275
        *value = temp;        
 
276
        return 0;
 
277
    }
 
278
    return -1;
 
279
} /* get_xml_ulong */
 
280
 
 
281
static int get_xml_double(
 
282
    xmlTextReaderPtr reader,
157
283
    double *value)
158
284
{
159
 
    double    temp;
160
 
    char     *str_ptr;
161
 
    char     *end_ptr;
162
 
 
163
 
    str_ptr = (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
164
 
    if (str_ptr == NULL) {
165
 
        rrd_set_error("get_double_from_node: xmlNodeListGetString failed.");
166
 
        return (-1);
167
 
    }
168
 
 
169
 
    if (strstr(str_ptr, "NaN") != NULL)
170
 
    {
171
 
        *value = DNAN;
172
 
        xmlFree(str_ptr);
 
285
    
 
286
    xmlChar *text;
 
287
    double temp;    
 
288
    if ((text = get_xml_text(reader))!= NULL){
 
289
        if (xmlStrcasestr(text,(xmlChar *)"nan")){
 
290
            *value = DNAN;
 
291
            xmlFree(text);
 
292
            return 0;            
 
293
        }
 
294
        else if (xmlStrcasestr(text,(xmlChar *)"-inf")){
 
295
            *value = -DINF;
 
296
            xmlFree(text);
 
297
            return 0;            
 
298
        }
 
299
        else if (xmlStrcasestr(text,(xmlChar *)"+inf")
 
300
                 || xmlStrcasestr(text,(xmlChar *)"inf")){
 
301
            *value = DINF;
 
302
            xmlFree(text);
 
303
            return 0;            
 
304
        }        
 
305
        errno = 0;
 
306
        temp = strtod((char *)text,NULL);
 
307
        if (errno>0){
 
308
            rrd_set_error("ling %d: get_xml_double from '%s' %s",
 
309
                          xmlTextReaderGetParserLineNumber(reader),
 
310
                          text,rrd_strerror(errno));
 
311
            xmlFree(text);        
 
312
            return -1;
 
313
        }
 
314
        xmlFree(text);        
 
315
        *value = temp;
173
316
        return 0;
174
317
    }
175
 
 
176
 
    end_ptr = NULL;
177
 
    temp = strtod(str_ptr, &end_ptr);
178
 
    xmlFree(str_ptr);
179
 
 
180
 
    if (str_ptr == end_ptr) {
181
 
        rrd_set_error
182
 
            ("get_double_from_node: Cannot parse buffer as double: %s",
183
 
             str_ptr);
184
 
        return (-1);
185
 
    }
186
 
 
187
 
    *value = temp;
188
 
 
189
 
    return (0);
190
 
}                       /* int get_double_from_node */
 
318
    return -1;
 
319
} /* get_xml_double */
 
320
 
191
321
 
192
322
static int value_check_range(
193
323
    rrd_value_t *rrd_value,
207
337
        *rrd_value = DNAN;
208
338
 
209
339
    return (0);
210
 
}                       /* int value_check_range */
 
340
} /* int value_check_range */
211
341
 
212
342
/*
213
343
 * Parse the <database> block within an RRA definition
214
344
 */
 
345
 
215
346
static int parse_tag_rra_database_row(
216
 
    xmlDoc * doc,
217
 
    xmlNode * node,
 
347
    xmlTextReaderPtr reader,
218
348
    rrd_t *rrd,
219
349
    rrd_value_t *rrd_value)
220
350
{
221
351
    unsigned int values_count = 0;
222
 
    xmlNode  *child;
223
352
    int       status;
224
 
 
 
353
    
225
354
    status = 0;
226
 
    for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
227
 
        if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0)
228
 
            || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0))
229
 
            /* ignore */ ;
230
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "v") == 0) {
231
 
            if (values_count < rrd->stat_head->ds_cnt) {
232
 
                status =
233
 
                    get_double_from_node(doc, child,
234
 
                                         rrd_value + values_count);
235
 
                if (status == 0)
236
 
                    value_check_range(rrd_value + values_count,
237
 
                                      rrd->ds_def + values_count);
238
 
            }
239
 
 
240
 
            values_count++;
241
 
        } else {
242
 
            rrd_set_error("parse_tag_rra_database_row: Unknown tag: %s",
243
 
                          child->name);
244
 
            status = -1;
 
355
    for (values_count = 0;values_count <  rrd->stat_head->ds_cnt;values_count++){
 
356
        if (expect_element(reader,"v") == 0){
 
357
            status = get_xml_double(reader,rrd_value + values_count);
 
358
            if (status == 0)
 
359
                value_check_range(rrd_value + values_count,
 
360
                                  rrd->ds_def + values_count);
 
361
            else
 
362
                break;            
 
363
        } else
 
364
            return -1;
 
365
        if (expect_element(reader,"/v") == -1){
 
366
            return -1;
245
367
        }
246
 
 
247
 
        if (status != 0)
248
 
            break;
249
 
    }                   /* for (child = node->xmlChildrenNode) */
250
 
 
251
 
    if (values_count != rrd->stat_head->ds_cnt) {
252
 
        rrd_set_error("parse_tag_rra_database_row: Row has %u values "
253
 
                      "and RRD has %lu data sources.",
254
 
                      values_count, rrd->stat_head->ds_cnt);
255
 
        status = -1;
256
368
    }
257
 
 
258
 
    return (status);
 
369
    return status;
259
370
}                       /* int parse_tag_rra_database_row */
260
371
 
261
372
static int parse_tag_rra_database(
262
 
    xmlDoc * doc,
263
 
    xmlNode * node,
264
 
    rrd_t *rrd)
 
373
    xmlTextReaderPtr reader,
 
374
    rrd_t *rrd )
265
375
{
266
376
    rra_def_t *cur_rra_def;
267
377
    unsigned int total_row_cnt;
268
 
    xmlNode  *child;
269
378
    int       status;
270
379
    int       i;
 
380
    xmlChar *element;
271
381
 
272
382
    total_row_cnt = 0;
273
383
    for (i = 0; i < (((int) rrd->stat_head->rra_cnt) - 1); i++)
276
386
    cur_rra_def = rrd->rra_def + i;
277
387
 
278
388
    status = 0;
279
 
    for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
280
 
        if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0)
281
 
            || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0))
282
 
            /* ignore */ ;
283
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "row") == 0) {
284
 
            rrd_value_t *temp;
285
 
            rrd_value_t *cur_rrd_value;
286
 
            unsigned int total_values_count = rrd->stat_head->ds_cnt
287
 
                * (total_row_cnt + 1);
 
389
    while ((element = get_xml_element(reader)) != NULL){        
 
390
        if (xmlStrcasecmp(element,(const xmlChar *)"row") == 0){
 
391
           rrd_value_t *temp;
 
392
           rrd_value_t *cur_rrd_value;
 
393
           unsigned int total_values_count = rrd->stat_head->ds_cnt
 
394
               * (total_row_cnt + 1);
288
395
 
289
396
            /* Allocate space for the new values.. */
290
397
            temp = (rrd_value_t *) realloc(rrd->rrd_value,
293
400
            if (temp == NULL) {
294
401
                rrd_set_error("parse_tag_rra_database: realloc failed.");
295
402
                status = -1;
296
 
                break;
 
403
               break;
297
404
            }
298
405
            rrd->rrd_value = temp;
299
406
            cur_rrd_value = rrd->rrd_value
304
411
            cur_rra_def->row_cnt++;
305
412
 
306
413
            status =
307
 
                parse_tag_rra_database_row(doc, child, rrd, cur_rrd_value);
308
 
        } /* if (xmlStrcmp (child->name, (const xmlChar *) "row") == 0) */
 
414
                parse_tag_rra_database_row(reader, rrd, cur_rrd_value);
 
415
            if (status == 0)
 
416
                status =  expect_element(reader,"/row");
 
417
        } /* if (xmlStrcasecmp(element,"row")) */
309
418
        else {
310
 
            rrd_set_error("parse_tag_rra_database: Unknown tag: %s",
311
 
                          child->name);
312
 
            status = -1;
 
419
            if ( xmlStrcasecmp(element,(const xmlChar *)"/database") == 0){
 
420
                xmlFree(element);                
 
421
                break;
 
422
            }
 
423
            else {
 
424
                rrd_set_error("line %d: found unexpected tag: %s",
 
425
                              xmlTextReaderGetParserLineNumber(reader),element);
 
426
                status = -1;
 
427
            }
313
428
        }
314
 
 
 
429
        xmlFree(element);        
315
430
        if (status != 0)
316
 
            break;
317
 
    }                   /* for (child = node->xmlChildrenNode) */
318
 
 
 
431
            break;        
 
432
    }
319
433
    return (status);
320
434
}                       /* int parse_tag_rra_database */
321
435
 
323
437
 * Parse the <cdp_prep> block within an RRA definition
324
438
 */
325
439
static int parse_tag_rra_cdp_prep_ds_history(
326
 
    xmlDoc * doc,
327
 
    xmlNode * node,
 
440
    xmlTextReaderPtr reader,
328
441
    cdp_prep_t *cdp_prep)
329
442
{
330
443
    /* Make `history_buffer' the same size as the scratch area, plus the
331
444
     * terminating NULL byte. */
332
 
    char      history_buffer[sizeof(((cdp_prep_t *)0)->scratch) + 1];
 
445
    xmlChar  *history;    
333
446
    char     *history_ptr;
334
 
    int       status;
335
447
    int       i;
336
 
 
337
 
    status = get_string_from_node(doc, node,
338
 
                                  history_buffer, sizeof(history_buffer));
339
 
    if (status != 0)
340
 
        return (-1);
341
 
 
342
 
    history_ptr = (char *) (&cdp_prep->scratch[0]);
343
 
    for (i = 0; history_buffer[i] != '\0'; i++)
344
 
        history_ptr[i] = (history_buffer[i] == '1') ? 1 : 0;
345
 
 
346
 
    return (0);
347
 
}                       /* int parse_tag_rra_cdp_prep_ds_history */
 
448
    if ((history = get_xml_text(reader)) != NULL){
 
449
        history_ptr = (char *) (&cdp_prep->scratch[0]);
 
450
        for (i = 0; history[i] != '\0'; i++)
 
451
            history_ptr[i] = (history[i] == '1') ? 1 : 0;
 
452
        xmlFree(history);        
 
453
        return 0;        
 
454
    }    
 
455
    return -1;    
 
456
}  /* int parse_tag_rra_cdp_prep_ds_history */
348
457
 
349
458
static int parse_tag_rra_cdp_prep_ds(
350
 
    xmlDoc * doc,
351
 
    xmlNode * node,
 
459
    xmlTextReaderPtr reader,
352
460
    rrd_t *rrd,
353
461
    cdp_prep_t *cdp_prep)
354
462
{
355
 
    xmlNode  *child;
356
463
    int       status;
357
 
 
 
464
    xmlChar *element;
358
465
    memset(cdp_prep, '\0', sizeof(cdp_prep_t));
359
466
 
360
 
    status = 0;
361
 
    for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
362
 
        if (atoi(rrd->stat_head->version) == 1) {
363
 
            cdp_prep->scratch[CDP_primary_val].u_val = 0.0;
364
 
            cdp_prep->scratch[CDP_secondary_val].u_val = 0.0;
365
 
        }
366
 
        if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0)
367
 
            || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0))
368
 
            /* ignore */ ;
369
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "primary_value") ==
370
 
                 0)
371
 
            status =
372
 
                get_double_from_node(doc, child,
373
 
                                     &cdp_prep->scratch[CDP_primary_val].
374
 
                                     u_val);
375
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "secondary_value")
376
 
                 == 0)
377
 
            status =
378
 
                get_double_from_node(doc, child,
379
 
                                     &cdp_prep->scratch[CDP_secondary_val].
380
 
                                     u_val);
381
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "intercept") == 0)
382
 
            status = get_double_from_node(doc, child,
 
467
    status = -1;
 
468
    
 
469
    if (atoi(rrd->stat_head->version) == 1) {
 
470
        cdp_prep->scratch[CDP_primary_val].u_val = 0.0;
 
471
        cdp_prep->scratch[CDP_secondary_val].u_val = 0.0;
 
472
    }
 
473
 
 
474
    while ((element = get_xml_element(reader)) != NULL){
 
475
        if (xmlStrcasecmp(element, (const xmlChar *) "primary_value") == 0)
 
476
            status =
 
477
                get_xml_double(reader,&cdp_prep->scratch[CDP_primary_val].u_val);
 
478
        else if (xmlStrcasecmp(element, (const xmlChar *) "secondary_value") == 0)
 
479
            status =
 
480
                get_xml_double(reader,&cdp_prep->scratch[CDP_secondary_val].u_val);
 
481
        else if (xmlStrcasecmp(element, (const xmlChar *) "intercept") == 0)
 
482
            status = get_xml_double(reader,
383
483
                                          &cdp_prep->
384
484
                                          scratch[CDP_hw_intercept].u_val);
385
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "last_intercept") ==
 
485
        else if (xmlStrcasecmp(element, (const xmlChar *) "last_intercept") ==
386
486
                 0)
387
487
            status =
388
 
                get_double_from_node(doc, child,
 
488
                get_xml_double(reader,
389
489
                                     &cdp_prep->
390
490
                                     scratch[CDP_hw_last_intercept].u_val);
391
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "slope") == 0)
392
 
            status = get_double_from_node(doc, child,
393
 
                                          &cdp_prep->scratch[CDP_hw_slope].
394
 
                                          u_val);
395
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "last_slope") == 0)
396
 
            status = get_double_from_node(doc, child,
397
 
                                          &cdp_prep->
398
 
                                          scratch[CDP_hw_last_slope].u_val);
399
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "nan_count") == 0)
400
 
            status = get_ulong_from_node(doc, child,
401
 
                                        &cdp_prep->
402
 
                                       scratch[CDP_null_count].u_cnt);
403
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "last_nan_count") ==
404
 
                 0)
405
 
            status =
406
 
                get_ulong_from_node(doc, child,
 
491
        else if (xmlStrcasecmp(element, (const xmlChar *) "slope") == 0)
 
492
            status = get_xml_double(reader,
 
493
                                    &cdp_prep->scratch[CDP_hw_slope].
 
494
                                    u_val);
 
495
        else if (xmlStrcasecmp(element, (const xmlChar *) "last_slope") == 0)
 
496
            status = get_xml_double(reader,
 
497
                                    &cdp_prep->
 
498
                                    scratch[CDP_hw_last_slope].u_val);
 
499
        else if (xmlStrcasecmp(element, (const xmlChar *) "nan_count") == 0)
 
500
            status = get_xml_ulong(reader,
407
501
                                   &cdp_prep->
408
 
                                  scratch[CDP_last_null_count].u_cnt);
409
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "seasonal") == 0)
410
 
            status = get_double_from_node(doc, child,
411
 
                                          &cdp_prep->scratch[CDP_hw_seasonal].
412
 
                                          u_val);
413
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "last_seasonal") ==
414
 
                 0)
415
 
            status =
416
 
                get_double_from_node(doc, child,
 
502
                                   scratch[CDP_null_count].u_cnt);
 
503
        else if (xmlStrcasecmp(element, (const xmlChar *) "last_nan_count") ==
 
504
                 0)
 
505
            status =
 
506
                get_xml_ulong(reader,
 
507
                              &cdp_prep->
 
508
                              scratch[CDP_last_null_count].u_cnt);
 
509
        else if (xmlStrcasecmp(element, (const xmlChar *) "seasonal") == 0)
 
510
            status = get_xml_double(reader,
 
511
                                    &cdp_prep->scratch[CDP_hw_seasonal].
 
512
                                    u_val);
 
513
        else if (xmlStrcasecmp(element, (const xmlChar *) "last_seasonal") ==
 
514
                 0)
 
515
            status =
 
516
                get_xml_double(reader,
417
517
                                     &cdp_prep->scratch[CDP_hw_last_seasonal].
418
518
                                     u_val);
419
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "init_flag") == 0)
420
 
            status = get_ulong_from_node(doc, child,
 
519
        else if (xmlStrcasecmp(element, (const xmlChar *) "init_flag") == 0)
 
520
            status = get_xml_ulong(reader,
421
521
                                        &cdp_prep->
422
522
                                       scratch[CDP_init_seasonal].u_cnt);
423
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "history") == 0)
424
 
            status = parse_tag_rra_cdp_prep_ds_history(doc, child, cdp_prep);
425
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "value") == 0)
426
 
            status = get_double_from_node(doc, child,
427
 
                                          &cdp_prep->scratch[CDP_val].u_val);
428
 
        else if (xmlStrcmp(child->name,
 
523
        else if (xmlStrcasecmp(element, (const xmlChar *) "history") == 0)
 
524
            status = parse_tag_rra_cdp_prep_ds_history(reader, cdp_prep);
 
525
        else if (xmlStrcasecmp(element, (const xmlChar *) "value") == 0)
 
526
            status = get_xml_double(reader,
 
527
                                    &cdp_prep->scratch[CDP_val].u_val);
 
528
        else if (xmlStrcasecmp(element,
429
529
                           (const xmlChar *) "unknown_datapoints") == 0)
430
 
            status = get_ulong_from_node(doc, child,
 
530
            status = get_xml_ulong(reader,
431
531
                                        &cdp_prep->
432
532
                                       scratch[CDP_unkn_pdp_cnt].u_cnt);
 
533
        else if (xmlStrcasecmp(element,
 
534
                               (const xmlChar *) "/ds") == 0){
 
535
            xmlFree(element);            
 
536
            break;
 
537
        }        
433
538
        else {
434
539
            rrd_set_error("parse_tag_rra_cdp_prep: Unknown tag: %s",
435
 
                          child->name);
 
540
                          element);
436
541
            status = -1;
437
 
        }
438
 
 
 
542
            xmlFree(element);            
 
543
            break;            
 
544
        }
 
545
        if (status != 0){
 
546
            xmlFree(element);
 
547
            break;
 
548
        }
 
549
        status = expect_element_end(reader,(char *)element);
 
550
        xmlFree(element);        
439
551
        if (status != 0)
440
552
            break;
441
 
    }
442
 
 
 
553
    }    
443
554
    return (status);
444
555
}                       /* int parse_tag_rra_cdp_prep_ds */
445
556
 
446
557
static int parse_tag_rra_cdp_prep(
447
 
    xmlDoc * doc,
448
 
    xmlNode * node,
 
558
    xmlTextReaderPtr reader,
449
559
    rrd_t *rrd,
450
560
    cdp_prep_t *cdp_prep)
451
561
{
452
 
    xmlNode  *child;
453
562
    int       status;
454
563
 
455
 
    unsigned int ds_count = 0;
 
564
    unsigned int ds_count;
456
565
 
457
566
    status = 0;
458
 
    for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
459
 
        if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0)
460
 
            || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0))
461
 
            /* ignore */ ;
462
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "ds") == 0) {
463
 
            if (ds_count >= rrd->stat_head->ds_cnt)
464
 
                status = -1;
465
 
            else {
466
 
                status = parse_tag_rra_cdp_prep_ds(doc, child, rrd,
467
 
                                                   cdp_prep + ds_count);
468
 
                ds_count++;
469
 
            }
 
567
    for ( ds_count = 0; ds_count < rrd->stat_head->ds_cnt;ds_count++){
 
568
        if (expect_element(reader,"ds") == 0) {
 
569
            status = parse_tag_rra_cdp_prep_ds(reader, rrd,
 
570
                                               cdp_prep + ds_count);
 
571
            if (status != 0)
 
572
                break;
470
573
        } else {
471
 
            rrd_set_error("parse_tag_rra_cdp_prep: Unknown tag: %s",
472
 
                          child->name);
473
 
            status = -1;
474
 
        }
475
 
 
476
 
        if (status != 0)
 
574
            status = -1;            
477
575
            break;
478
 
    }
479
 
 
480
 
    if (ds_count != rrd->stat_head->ds_cnt) {
481
 
        rrd_set_error("parse_tag_rra_cdp_prep: There are %i data sources in "
482
 
                      "the RRD file, but %i in this cdp_prep block!",
483
 
                      (int) rrd->stat_head->ds_cnt, ds_count);
484
 
        status = -1;
485
 
    }
486
 
 
 
576
        }        
 
577
    }
 
578
    if (status == 0)
 
579
        status =  expect_element(reader,"/cdp_prep");
487
580
    return (status);
488
581
}                       /* int parse_tag_rra_cdp_prep */
489
582
 
491
584
 * Parse the <params> block within an RRA definition
492
585
 */
493
586
static int parse_tag_rra_params(
494
 
    xmlDoc * doc,
495
 
    xmlNode * node,
 
587
    xmlTextReaderPtr reader,
496
588
    rra_def_t *rra_def)
497
589
{
498
 
    xmlNode  *child;
 
590
    xmlChar *element;
499
591
    int       status;
500
592
 
501
 
    status = 0;
502
 
    for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
503
 
        if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0)
504
 
            || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0))
505
 
            /* ignore */ ;
 
593
    status = -1;
 
594
    while ((element = get_xml_element(reader)) != NULL){
506
595
        /*
507
596
         * Parameters for CF_HWPREDICT
508
597
         */
509
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "hw_alpha") == 0)
510
 
            status = get_double_from_node(doc, child,
 
598
        if (xmlStrcasecmp(element, (const xmlChar *) "hw_alpha") == 0)
 
599
            status = get_xml_double(reader,
511
600
                                          &rra_def->par[RRA_hw_alpha].u_val);
512
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "hw_beta") == 0)
513
 
            status = get_double_from_node(doc, child,
 
601
        else if (xmlStrcasecmp(element, (const xmlChar *) "hw_beta") == 0)
 
602
            status = get_xml_double(reader,
514
603
                                          &rra_def->par[RRA_hw_beta].u_val);
515
 
        else if (xmlStrcmp(child->name,
 
604
        else if (xmlStrcasecmp(element,
516
605
                           (const xmlChar *) "dependent_rra_idx") == 0)
517
 
            status = get_ulong_from_node(doc, child,
 
606
            status = get_xml_ulong(reader,
518
607
                                        &rra_def->
519
608
                                       par[RRA_dependent_rra_idx].u_cnt);
520
609
        /*
521
610
         * Parameters for CF_SEASONAL and CF_DEVSEASONAL
522
611
         */
523
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "seasonal_gamma") ==
 
612
        else if (xmlStrcasecmp(element, (const xmlChar *) "seasonal_gamma") ==
524
613
                 0)
525
614
            status =
526
 
                get_double_from_node(doc, child,
 
615
                get_xml_double(reader,
527
616
                                     &rra_def->par[RRA_seasonal_gamma].u_val);
528
 
        else if (xmlStrcmp
529
 
                 (child->name, (const xmlChar *) "seasonal_smooth_idx") == 0)
 
617
        else if (xmlStrcasecmp
 
618
                 (element, (const xmlChar *) "seasonal_smooth_idx") == 0)
530
619
            status =
531
 
                get_ulong_from_node(doc, child,
 
620
                get_xml_ulong(reader,
532
621
                                   &rra_def->
533
622
                                  par[RRA_seasonal_smooth_idx].u_cnt);
534
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "smoothing_window")
 
623
        else if (xmlStrcasecmp(element, (const xmlChar *) "smoothing_window")
535
624
                 == 0)
536
625
            status =
537
 
                get_double_from_node(doc, child,
 
626
                get_xml_double(reader,
538
627
                                     &rra_def->
539
628
                                     par[RRA_seasonal_smoothing_window].
540
629
                                     u_val);
542
631
        /*
543
632
         * Parameters for CF_FAILURES
544
633
         */
545
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "delta_pos") == 0)
546
 
            status = get_double_from_node(doc, child,
 
634
        else if (xmlStrcasecmp(element, (const xmlChar *) "delta_pos") == 0)
 
635
            status = get_xml_double(reader,
547
636
                                          &rra_def->par[RRA_delta_pos].u_val);
548
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "delta_neg") == 0)
549
 
            status = get_double_from_node(doc, child,
 
637
        else if (xmlStrcasecmp(element, (const xmlChar *) "delta_neg") == 0)
 
638
            status = get_xml_double(reader,
550
639
                                          &rra_def->par[RRA_delta_neg].u_val);
551
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "window_len") == 0)
552
 
            status = get_ulong_from_node(doc, child,
 
640
        else if (xmlStrcasecmp(element, (const xmlChar *) "window_len") == 0)
 
641
            status = get_xml_ulong(reader,
553
642
                                        &rra_def->par[RRA_window_len].
554
643
                                       u_cnt);
555
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "failure_threshold")
 
644
        else if (xmlStrcasecmp(element, (const xmlChar *) "failure_threshold")
556
645
                 == 0)
557
646
            status =
558
 
                get_ulong_from_node(doc, child,
 
647
                get_xml_ulong(reader,
559
648
                                   &rra_def->
560
649
                                  par[RRA_failure_threshold].u_cnt);
561
650
        /*
562
651
         * Parameters for CF_AVERAGE, CF_MAXIMUM, CF_MINIMUM, and CF_LAST
563
652
         */
564
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "xff") == 0)
565
 
            status = get_double_from_node(doc, child,
 
653
        else if (xmlStrcasecmp(element, (const xmlChar *) "xff") == 0)
 
654
            status = get_xml_double(reader,
566
655
                                          &rra_def->par[RRA_cdp_xff_val].
567
656
                                          u_val);
568
657
        /*
569
658
         * Compatibility code for 1.0.49
570
659
         */
571
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "value") == 0) {  /* {{{ */
 
660
        else if (xmlStrcasecmp(element, (const xmlChar *) "value") == 0) {  /* {{{ */
572
661
            unsigned int i = 0;
573
662
 
574
 
            while (42) {
575
 
                if (i >= ARRAY_LENGTH(rra_def->par)) {
576
 
                    status = -1;
577
 
                    break;
578
 
                }
579
 
 
 
663
            for (i=0;i<ARRAY_LENGTH(rra_def->par);i++){
580
664
                if ((i == RRA_dependent_rra_idx)
581
665
                    || (i == RRA_seasonal_smooth_idx)
582
666
                    || (i == RRA_failure_threshold))
583
 
                    status = get_ulong_from_node(doc, child,
 
667
                    status = get_xml_ulong(reader,
584
668
                                                &rra_def->par[i].
585
669
                                               u_cnt);
586
670
                else
587
 
                    status = get_double_from_node(doc, child,
 
671
                    status = get_xml_double(reader,
588
672
                                                  &rra_def->par[i].u_val);
589
673
 
590
674
                if (status != 0)
591
675
                    break;
592
 
 
593
 
                /* When this loops exits (sucessfully) `child' points to the last
594
 
                 * `value' tag in the list. */
595
 
                if ((child->next == NULL)
596
 
                    || (xmlStrcmp(child->name, (const xmlChar *) "value") !=
597
 
                        0))
598
 
                    break;
599
 
 
600
 
                child = child->next;
601
 
                i++;
 
676
                if ( i-1 < ARRAY_LENGTH(rra_def->par)){
 
677
                    status = expect_element(reader,"/value");
 
678
                    if (status == 0){
 
679
                        status  = expect_element(reader,"value");
 
680
                    }
 
681
                }
 
682
                if (status != 0){
 
683
                    break;                    
 
684
                }
602
685
            }
603
 
        } /* }}} */
 
686
        }  /* }}} */        
 
687
        else if (xmlStrcasecmp(element,(const xmlChar *) "/params") == 0){
 
688
            xmlFree(element);            
 
689
            return status;
 
690
        }  /* }}} */        
604
691
        else {
605
 
            rrd_set_error("parse_tag_rra_params: Unknown tag: %s",
606
 
                          child->name);
 
692
            rrd_set_error("line %d: parse_tag_rra_params: Unknown tag: %s",
 
693
                          xmlTextReaderGetParserLineNumber(reader),element);
607
694
            status = -1;
608
695
        }
609
 
 
 
696
        status = expect_element_end(reader,(char *)element);
 
697
        xmlFree(element);        
610
698
        if (status != 0)
611
699
            break;
612
700
    }
613
 
 
614
701
    return (status);
615
702
}                       /* int parse_tag_rra_params */
616
703
 
618
705
 * Parse an RRA definition
619
706
 */
620
707
static int parse_tag_rra_cf(
621
 
    xmlDoc * doc,
622
 
    xmlNode * node,
 
708
    xmlTextReaderPtr reader,
623
709
    rra_def_t *rra_def)
624
710
{
625
711
    int       status;
626
712
 
627
 
    status = get_string_from_node(doc, node,
 
713
    status = get_xml_string(reader,
628
714
                                  rra_def->cf_nam, sizeof(rra_def->cf_nam));
629
715
    if (status != 0)
630
 
        return (-1);
 
716
        return status;
631
717
 
632
718
    status = cf_conv(rra_def->cf_nam);
633
719
    if (status == -1) {
634
720
        rrd_set_error("parse_tag_rra_cf: Unknown consolidation function: %s",
635
721
                      rra_def->cf_nam);
636
 
        return (-1);
 
722
        return -1;
637
723
    }
638
724
 
639
 
    return (0);
 
725
    return 0;
640
726
}                       /* int parse_tag_rra_cf */
641
727
 
642
728
static int parse_tag_rra(
643
 
    xmlDoc * doc,
644
 
    xmlNode * node,
 
729
    xmlTextReaderPtr reader,
645
730
    rrd_t *rrd)
646
731
{
647
 
    xmlNode  *child;
648
732
    int       status;
649
 
 
 
733
    xmlChar *element;
 
734
    
650
735
    rra_def_t *cur_rra_def;
651
736
    cdp_prep_t *cur_cdp_prep;
652
737
    rra_ptr_t *cur_rra_ptr;
705
790
    rrd->stat_head->rra_cnt++;
706
791
 
707
792
    status = 0;
708
 
    for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
709
 
        if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0)
710
 
            || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0))
711
 
            /* ignore */ ;
712
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "cf") == 0)
713
 
            status = parse_tag_rra_cf(doc, child, cur_rra_def);
714
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "pdp_per_row") == 0)
715
 
            status = get_ulong_from_node(doc, child,
 
793
    while ((element = get_xml_element(reader)) != NULL){
 
794
        if (xmlStrcasecmp(element, (const xmlChar *) "cf") == 0)
 
795
            status = parse_tag_rra_cf(reader, cur_rra_def);
 
796
        else if (xmlStrcasecmp(element, (const xmlChar *) "pdp_per_row") == 0)
 
797
            status = get_xml_ulong(reader,
716
798
                                        &cur_rra_def->pdp_cnt);
717
799
        else if (atoi(rrd->stat_head->version) == 1
718
 
                 && xmlStrcmp(child->name, (const xmlChar *) "xff") == 0)
719
 
            status = get_double_from_node(doc, child,
 
800
                 && xmlStrcasecmp(element, (const xmlChar *) "xff") == 0)
 
801
            status = get_xml_double(reader,
720
802
                                          (double *) &cur_rra_def->
721
803
                                          par[RRA_cdp_xff_val].u_val);
722
804
        else if (atoi(rrd->stat_head->version) >= 2
723
 
                 && xmlStrcmp(child->name, (const xmlChar *) "params") == 0)
724
 
            status = parse_tag_rra_params(doc, child, cur_rra_def);
725
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "cdp_prep") == 0)
726
 
            status = parse_tag_rra_cdp_prep(doc, child, rrd, cur_cdp_prep);
727
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "database") == 0)
728
 
            status = parse_tag_rra_database(doc, child, rrd);
729
 
        else {
730
 
            rrd_set_error("parse_tag_rra: Unknown tag: %s", child->name);
731
 
            status = -1;
732
 
        }
733
 
 
734
 
        if (status != 0)
735
 
            break;
736
 
    }
737
 
 
 
805
                 && xmlStrcasecmp(element, (const xmlChar *) "params") == 0){            
 
806
            xmlFree(element);
 
807
            status = parse_tag_rra_params(reader, cur_rra_def);
 
808
            if (status == 0)
 
809
                continue;
 
810
            else
 
811
                return status;
 
812
        }
 
813
        else if (xmlStrcasecmp(element, (const xmlChar *) "cdp_prep") == 0){
 
814
            xmlFree(element);
 
815
            status = parse_tag_rra_cdp_prep(reader, rrd, cur_cdp_prep);
 
816
            if (status == 0)
 
817
                continue;
 
818
            else
 
819
                return status;
 
820
        }        
 
821
        else if (xmlStrcasecmp(element, (const xmlChar *) "database") == 0){            
 
822
            xmlFree(element);
 
823
            status = parse_tag_rra_database(reader, rrd);
 
824
            if (status == 0)
 
825
                continue;
 
826
            else
 
827
                return status;
 
828
        }
 
829
        else if (xmlStrcasecmp(element,(const xmlChar *) "/rra") == 0){
 
830
            xmlFree(element);            
 
831
            return status;
 
832
        }  /* }}} */        
 
833
       else {
 
834
            rrd_set_error("line %d: parse_tag_rra: Unknown tag: %s",
 
835
                          xmlTextReaderGetParserLineNumber(reader), element);
 
836
            status = -1;            
 
837
        }
 
838
        if (status != 0) {
 
839
            xmlFree(element);
 
840
            return status;
 
841
        }        
 
842
        status = expect_element_end(reader,(char *)element);
 
843
        xmlFree(element);
 
844
        if (status != 0) {
 
845
            return status;
 
846
        }        
 
847
    }    
738
848
    /* Set the RRA pointer to a random location */
739
 
#ifdef WIN32
740
 
    cur_rra_ptr->cur_row = rand() % cur_rra_def->row_cnt;
741
 
#else
742
 
    cur_rra_ptr->cur_row = random() % cur_rra_def->row_cnt;
743
 
#endif
 
849
    cur_rra_ptr->cur_row = rrd_random() % cur_rra_def->row_cnt;
744
850
 
745
851
    return (status);
746
852
}                       /* int parse_tag_rra */
749
855
 * Parse a DS definition
750
856
 */
751
857
static int parse_tag_ds_cdef(
752
 
    xmlDoc * doc,
753
 
    xmlNode * node,
 
858
    xmlTextReaderPtr reader,
754
859
    rrd_t *rrd)
755
860
{
756
 
    char      buffer[1024];
757
 
    int       status;
758
 
 
759
 
    status = get_string_from_node(doc, node, buffer, sizeof(buffer));
760
 
    if (status != 0)
761
 
        return (-1);
762
 
 
763
 
    /* We're always working on the last DS that has been added to the structure
764
 
     * when we get here */
765
 
    parseCDEF_DS(buffer, rrd, rrd->stat_head->ds_cnt - 1);
766
 
 
767
 
    return (0);
 
861
    xmlChar *cdef;
 
862
 
 
863
    cdef = get_xml_text(reader);
 
864
    if (cdef != NULL){
 
865
        /* We're always working on the last DS that has been added to the structure
 
866
         * when we get here */
 
867
        parseCDEF_DS((char *)cdef, rrd, rrd->stat_head->ds_cnt - 1);
 
868
        xmlFree(cdef);
 
869
        if (rrd_test_error())
 
870
            return -1;
 
871
        else            
 
872
            return 0;        
 
873
    }
 
874
    return -1;
768
875
}                       /* int parse_tag_ds_cdef */
769
876
 
770
877
static int parse_tag_ds_type(
771
 
    xmlDoc * doc,
772
 
    xmlNode * node,
 
878
    xmlTextReaderPtr reader,
773
879
    ds_def_t *ds_def)
774
880
{
775
 
    int       status;
776
 
 
777
 
    status = get_string_from_node(doc, node,
778
 
                                  ds_def->dst, sizeof(ds_def->dst));
779
 
    if (status != 0)
780
 
        return (-1);
781
 
 
782
 
    status = dst_conv(ds_def->dst);
783
 
    if (status == -1) {
784
 
        rrd_set_error("parse_tag_ds_type: Unknown data source type: %s",
785
 
                      ds_def->dst);
786
 
        return (-1);
 
881
    char *dst;
 
882
    dst = (char *)get_xml_text(reader);
 
883
    if (dst != NULL){
 
884
        int status;
 
885
        status = dst_conv(dst);
 
886
        if (status == -1) {
 
887
            rrd_set_error("parse_tag_ds_type: Unknown data source type: %s",
 
888
                          dst);
 
889
            return -1;
 
890
        }
 
891
        strncpy(ds_def->dst,dst,sizeof(ds_def->dst)-1);
 
892
        ds_def->dst[sizeof(ds_def->dst)-1] = '\0';
 
893
        xmlFree(dst);
 
894
        return 0;        
787
895
    }
788
 
 
789
 
    return (0);
 
896
    return -1;
790
897
}                       /* int parse_tag_ds_type */
791
898
 
792
899
static int parse_tag_ds(
793
 
    xmlDoc * doc,
794
 
    xmlNode * node,
 
900
    xmlTextReaderPtr reader,
795
901
    rrd_t *rrd)
796
902
{
797
 
    xmlNode  *child;
798
903
    int       status;
799
 
 
 
904
    xmlChar  *element;
 
905
    
800
906
    ds_def_t *cur_ds_def;
801
907
    pdp_prep_t *cur_pdp_prep;
802
908
 
847
953
    rrd->stat_head->ds_cnt++;
848
954
 
849
955
    status = 0;
850
 
    for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
851
 
        if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0)
852
 
            || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0))
853
 
            /* ignore */ ;
854
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "name") == 0)
855
 
            status = get_string_from_node(doc, child,
856
 
                                          cur_ds_def->ds_nam,
857
 
                                          sizeof(cur_ds_def->ds_nam));
858
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "type") == 0)
859
 
            status = parse_tag_ds_type(doc, child, cur_ds_def);
860
 
        else if (xmlStrcmp(child->name,
 
956
    while ((element = get_xml_element(reader)) != NULL){
 
957
        if (xmlStrcasecmp(element, (const xmlChar *) "name") == 0){
 
958
            status = get_xml_string(reader,cur_ds_def->ds_nam,sizeof(cur_ds_def->ds_nam));
 
959
        }
 
960
        else if (xmlStrcasecmp(element, (const xmlChar *) "type") == 0)
 
961
            status = parse_tag_ds_type(reader, cur_ds_def);
 
962
        else if (xmlStrcasecmp(element,
861
963
                           (const xmlChar *) "minimal_heartbeat") == 0)
862
 
            status = get_ulong_from_node(doc, child,
 
964
            status = get_xml_ulong(reader,
863
965
                                        &cur_ds_def->par[DS_mrhb_cnt].
864
966
                                       u_cnt);
865
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "min") == 0)
866
 
            status = get_double_from_node(doc, child,
 
967
        else if (xmlStrcasecmp(element, (const xmlChar *) "min") == 0)
 
968
            status = get_xml_double(reader,
867
969
                                          &cur_ds_def->par[DS_min_val].u_val);
868
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "max") == 0)
869
 
            status = get_double_from_node(doc, child,
 
970
        else if (xmlStrcasecmp(element, (const xmlChar *) "max") == 0)
 
971
            status = get_xml_double(reader,
870
972
                                          &cur_ds_def->par[DS_max_val].u_val);
871
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "cdef") == 0)
872
 
            status = parse_tag_ds_cdef(doc, child, rrd);
873
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "last_ds") == 0)
874
 
            status = get_string_from_node(doc, child,
 
973
        else if (xmlStrcasecmp(element, (const xmlChar *) "cdef") == 0)
 
974
            status = parse_tag_ds_cdef(reader, rrd);
 
975
        else if (xmlStrcasecmp(element, (const xmlChar *) "last_ds") == 0)
 
976
            status = get_xml_string(reader,
875
977
                                          cur_pdp_prep->last_ds,
876
978
                                          sizeof(cur_pdp_prep->last_ds));
877
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "value") == 0)
878
 
            status = get_double_from_node(doc, child,
 
979
        else if (xmlStrcasecmp(element, (const xmlChar *) "value") == 0)
 
980
            status = get_xml_double(reader,
879
981
                                          &cur_pdp_prep->scratch[PDP_val].
880
982
                                          u_val);
881
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "unknown_sec") == 0)
882
 
            status = get_ulong_from_node(doc, child,
 
983
        else if (xmlStrcasecmp(element, (const xmlChar *) "unknown_sec") == 0)
 
984
            status = get_xml_ulong(reader,
883
985
                                        &cur_pdp_prep->
884
986
                                       scratch[PDP_unkn_sec_cnt].u_cnt);
 
987
        else if (xmlStrcasecmp(element, (const xmlChar *) "/ds") == 0) {
 
988
            xmlFree(element);            
 
989
            break;
 
990
        }        
885
991
        else {
886
 
            rrd_set_error("parse_tag_ds: Unknown tag: %s", child->name);
 
992
            rrd_set_error("parse_tag_ds: Unknown tag: %s", element);
887
993
            status = -1;
 
994
        }        
 
995
        if (status != 0) {            
 
996
            xmlFree(element);        
 
997
            break;
888
998
        }
889
 
 
 
999
        status = expect_element_end(reader,(char *)element);
 
1000
        xmlFree(element);        
890
1001
        if (status != 0)
891
 
            break;
 
1002
            break;        
892
1003
    }
893
 
 
 
1004
    
894
1005
    return (status);
895
1006
}                       /* int parse_tag_ds */
896
1007
 
898
1009
 * Parse root nodes
899
1010
 */
900
1011
static int parse_tag_rrd(
901
 
    xmlDoc * doc,
902
 
    xmlNode * node,
 
1012
    xmlTextReaderPtr reader,
903
1013
    rrd_t *rrd)
904
1014
{
905
 
    xmlNode  *child;
906
1015
    int       status;
907
 
 
 
1016
    xmlChar *element;
 
1017
    
908
1018
    status = 0;
909
 
    for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
910
 
        if ((xmlStrcmp(child->name, (const xmlChar *) "comment") == 0)
911
 
            || (xmlStrcmp(child->name, (const xmlChar *) "text") == 0))
912
 
            /* ignore */ ;
913
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "version") == 0)
914
 
            status = get_string_from_node(doc, child,
 
1019
    while ((element = get_xml_element(reader)) != NULL ){
 
1020
        if (xmlStrcasecmp(element, (const xmlChar *) "version") == 0)
 
1021
            status = get_xml_string(reader,
915
1022
                                          rrd->stat_head->version,
916
1023
                                          sizeof(rrd->stat_head->version));
917
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "step") == 0)
918
 
            status = get_ulong_from_node(doc, child,
 
1024
        else if (xmlStrcasecmp(element, (const xmlChar *) "step") == 0)
 
1025
            status = get_xml_ulong(reader,
919
1026
                                        &rrd->stat_head->pdp_step);
920
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "lastupdate") == 0)
921
 
            status = get_long_from_node(doc, child,
922
 
                                        &rrd->live_head->last_up);
923
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "ds") == 0)
924
 
            status = parse_tag_ds(doc, child, rrd);
925
 
        else if (xmlStrcmp(child->name, (const xmlChar *) "rra") == 0)
926
 
            status = parse_tag_rra(doc, child, rrd);
 
1027
        else if (xmlStrcasecmp(element, (const xmlChar *) "lastupdate") == 0) {
 
1028
                status = get_xml_time_t(reader, &rrd->live_head->last_up);
 
1029
        }
 
1030
        else if (xmlStrcasecmp(element, (const xmlChar *) "ds") == 0){            
 
1031
            xmlFree(element);
 
1032
            status = parse_tag_ds(reader, rrd);
 
1033
            /* as we come back the </ds> tag is already gone */
 
1034
            if (status == 0)
 
1035
                continue;
 
1036
            else
 
1037
                return status;
 
1038
        }        
 
1039
        else if (xmlStrcasecmp(element, (const xmlChar *) "rra") == 0){            
 
1040
            xmlFree(element);
 
1041
            status = parse_tag_rra(reader, rrd);
 
1042
            if (status == 0)
 
1043
                continue;
 
1044
            else
 
1045
                return status;
 
1046
        }
 
1047
        else if (xmlStrcasecmp(element, (const xmlChar *) "/rrd") == 0) {
 
1048
            xmlFree(element);
 
1049
            return status;
 
1050
        }
927
1051
        else {
928
 
            rrd_set_error("parse_tag_rrd: Unknown tag: %s", child->name);
 
1052
            rrd_set_error("parse_tag_rrd: Unknown tag: %s", element);
929
1053
            status = -1;
930
1054
        }
931
1055
 
 
1056
        if (status != 0){
 
1057
            xmlFree(element);
 
1058
            break;
 
1059
        }        
 
1060
        status = expect_element_end(reader,(char *)element);
 
1061
        xmlFree(element);        
932
1062
        if (status != 0)
933
 
            break;
 
1063
            break;        
934
1064
    }
935
 
 
936
1065
    return (status);
937
1066
}                       /* int parse_tag_rrd */
938
1067
 
939
1068
static rrd_t *parse_file(
940
1069
    const char *filename)
941
1070
{
942
 
    xmlDoc   *doc;
943
 
    xmlNode  *cur;
 
1071
    xmlTextReaderPtr reader;
944
1072
    int       status;
945
1073
 
946
1074
    rrd_t    *rrd;
947
1075
 
948
 
    doc = xmlParseFile(filename);
949
 
    if (doc == NULL) {
950
 
        rrd_set_error("Document not parsed successfully.");
951
 
        return (NULL);
952
 
    }
953
 
 
954
 
    cur = xmlDocGetRootElement(doc);
955
 
    if (cur == NULL) {
956
 
        rrd_set_error("Document is empty.");
957
 
        xmlFreeDoc(doc);
958
 
        return (NULL);
959
 
    }
960
 
 
961
 
    if (xmlStrcmp(cur->name, (const xmlChar *) "rrd") != 0) {
962
 
        rrd_set_error
963
 
            ("Document of the wrong type, root node is not \"rrd\".");
964
 
        xmlFreeDoc(doc);
 
1076
    reader = xmlNewTextReaderFilename(filename);
 
1077
    if (reader == NULL) {
 
1078
        rrd_set_error("Could not create xml reader for: %s",filename);
 
1079
        return (NULL);
 
1080
    }
 
1081
 
 
1082
    if (expect_element(reader,"rrd") != 0) {
 
1083
        xmlFreeTextReader(reader);
965
1084
        return (NULL);
966
1085
    }
967
1086
 
968
1087
    rrd = (rrd_t *) malloc(sizeof(rrd_t));
969
1088
    if (rrd == NULL) {
970
1089
        rrd_set_error("parse_file: malloc failed.");
971
 
        xmlFreeDoc(doc);
 
1090
        xmlFreeTextReader(reader);
972
1091
        return (NULL);
973
1092
    }
974
1093
    memset(rrd, '\0', sizeof(rrd_t));
976
1095
    rrd->stat_head = (stat_head_t *) malloc(sizeof(stat_head_t));
977
1096
    if (rrd->stat_head == NULL) {
978
1097
        rrd_set_error("parse_tag_rrd: malloc failed.");
979
 
        xmlFreeDoc(doc);
 
1098
        xmlFreeTextReader(reader);
980
1099
        free(rrd);
981
1100
        return (NULL);
982
1101
    }
988
1107
    rrd->live_head = (live_head_t *) malloc(sizeof(live_head_t));
989
1108
    if (rrd->live_head == NULL) {
990
1109
        rrd_set_error("parse_tag_rrd: malloc failed.");
991
 
        xmlFreeDoc(doc);
 
1110
        xmlFreeTextReader(reader);
992
1111
        free(rrd->stat_head);
993
1112
        free(rrd);
994
1113
        return (NULL);
995
1114
    }
996
1115
    memset(rrd->live_head, '\0', sizeof(live_head_t));
997
1116
 
998
 
    status = parse_tag_rrd(doc, cur, rrd);
999
 
 
1000
 
    xmlFreeDoc(doc);
 
1117
    status = parse_tag_rrd(reader, rrd);
 
1118
 
 
1119
    xmlFreeTextReader(reader);
 
1120
 
1001
1121
    if (status != 0) {
1002
 
        rrd_free(rrd);
 
1122
        local_rrd_free(rrd);
1003
1123
        rrd = NULL;
1004
1124
    }
1005
1125
 
1087
1207
    char **argv)
1088
1208
{
1089
1209
    rrd_t    *rrd;
1090
 
 
1091
 
#ifdef WIN32
1092
 
    srand((unsigned int) time(NULL));
1093
 
#else
1094
 
    srandom((unsigned int) time(NULL) + (unsigned int) getpid());
1095
 
#endif
 
1210
    char     *old_locale;
1096
1211
    /* init rrd clean */
1097
1212
    optind = 0;
1098
1213
    opterr = 0;         /* initialize getopt */
1134
1249
        return (-1);
1135
1250
    }
1136
1251
 
 
1252
    old_locale = setlocale(LC_NUMERIC, "C");
 
1253
 
1137
1254
    rrd = parse_file(argv[optind]);
 
1255
 
 
1256
    setlocale(LC_NUMERIC, old_locale);
 
1257
 
1138
1258
    if (rrd == NULL)
1139
1259
        return (-1);
1140
 
 
 
1260
    
1141
1261
    if (write_file(argv[optind + 1], rrd) != 0) {
1142
 
        rrd_free(rrd);
 
1262
        local_rrd_free(rrd);
1143
1263
        return (-1);
1144
1264
    }
1145
 
 
1146
 
    rrd_free(rrd);
 
1265
    local_rrd_free(rrd);
 
1266
 
 
1267
 
1147
1268
    return (0);
1148
1269
}                       /* int rrd_restore */
1149
1270