252018f53b2942d2f25583375fe7b086c54c310a
1 #ifdef __cplusplus
2 extern "C" {
3 #endif
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "XSUB.h"
9 #ifdef __cplusplus
10 }
11 #endif
13 /*
14 * rrd_tool.h includes config.h, but at least on Ubuntu Breezy Badger
15 * 5.10 with gcc 4.0.2, the C preprocessor picks up Perl's config.h
16 * which is included from the Perl includes and never reads rrdtool's
17 * config.h. Without including rrdtool's config.h, this module does
18 * not compile, so include it here with an explicit path.
19 *
20 * Because rrdtool's config.h redefines VERSION which is originally
21 * set via Perl's Makefile.PL and passed down to the C compiler's
22 * command line, save the original value and reset it after the
23 * includes.
24 */
25 #define VERSION_SAVED VERSION
26 #undef VERSION
27 #ifndef WIN32
28 #include "../../rrd_config.h"
29 #endif
30 #include "../../src/rrd_tool.h"
31 #undef VERSION
32 #define VERSION VERSION_SAVED
33 #undef VERSION_SAVED
35 #define rrdcode(name) \
36 argv = (char **) malloc((items+1)*sizeof(char *));\
37 argv[0] = "dummy";\
38 for (i = 0; i < items; i++) { \
39 STRLEN len; \
40 char *handle= SvPV(ST(i),len);\
41 /* actually copy the data to make sure possible modifications \
42 on the argv data does not backfire into perl */ \
43 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char)); \
44 strcpy(argv[i+1],handle); \
45 } \
46 rrd_clear_error();\
47 RETVAL=name(items+1,argv); \
48 for (i=0; i < items; i++) {\
49 free(argv[i+1]);\
50 } \
51 free(argv);\
52 \
53 if (rrd_test_error()) XSRETURN_UNDEF;
55 #define hvs(VAL) hv_store_ent(hash, sv_2mortal(newSVpv(data->key,0)),VAL,0)
57 #define rrdinfocode(name) \
58 /* prepare argument list */ \
59 argv = (char **) malloc((items+1)*sizeof(char *)); \
60 argv[0] = "dummy"; \
61 for (i = 0; i < items; i++) { \
62 STRLEN len; \
63 char *handle= SvPV(ST(i),len); \
64 /* actually copy the data to make sure possible modifications \
65 on the argv data does not backfire into perl */ \
66 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char)); \
67 strcpy(argv[i+1],handle); \
68 } \
69 rrd_clear_error(); \
70 data=name(items+1, argv); \
71 for (i=0; i < items; i++) { \
72 free(argv[i+1]); \
73 } \
74 free(argv); \
75 if (rrd_test_error()) XSRETURN_UNDEF; \
76 hash = newHV(); \
77 save=data; \
78 while (data) { \
79 /* the newSV will get copied by hv so we create it as a mortal \
80 to make sure it does not keep hanging round after the fact */ \
81 switch (data->type) { \
82 case RD_I_VAL: \
83 if (isnan(data->value.u_val)) \
84 hvs(&PL_sv_undef); \
85 else \
86 hvs(newSVnv(data->value.u_val)); \
87 break; \
88 case RD_I_INT: \
89 hvs(newSViv(data->value.u_int)); \
90 break; \
91 case RD_I_CNT: \
92 hvs(newSViv(data->value.u_cnt)); \
93 break; \
94 case RD_I_STR: \
95 hvs(newSVpv(data->value.u_str,0)); \
96 break; \
97 case RD_I_BLO: \
98 hvs(newSVpv(data->value.u_blo.ptr,data->value.u_blo.size)); \
99 break; \
100 } \
101 data = data->next; \
102 } \
103 rrd_info_free(save); \
104 RETVAL = newRV_noinc((SV*)hash);
106 /*
107 * should not be needed if libc is linked (see ntmake.pl)
108 #ifdef WIN32
109 #define free free
110 #define malloc malloc
111 #define realloc realloc
112 #endif
113 */
116 MODULE = RRDs PACKAGE = RRDs PREFIX = rrd_
118 BOOT:
119 #ifdef MUST_DISABLE_SIGFPE
120 signal(SIGFPE,SIG_IGN);
121 #endif
122 #ifdef MUST_DISABLE_FPMASK
123 fpsetmask(0);
124 #endif
126 SV*
127 rrd_error()
128 CODE:
129 if (! rrd_test_error()) XSRETURN_UNDEF;
130 RETVAL = newSVpv(rrd_get_error(),0);
131 OUTPUT:
132 RETVAL
134 int
135 rrd_last(...)
136 PROTOTYPE: @
137 PREINIT:
138 int i;
139 char **argv;
140 CODE:
141 rrdcode(rrd_last);
142 OUTPUT:
143 RETVAL
145 int
146 rrd_first(...)
147 PROTOTYPE: @
148 PREINIT:
149 int i;
150 char **argv;
151 CODE:
152 rrdcode(rrd_first);
153 OUTPUT:
154 RETVAL
156 int
157 rrd_create(...)
158 PROTOTYPE: @
159 PREINIT:
160 int i;
161 char **argv;
162 CODE:
163 rrdcode(rrd_create);
164 RETVAL = 1;
165 OUTPUT:
166 RETVAL
168 int
169 rrd_update(...)
170 PROTOTYPE: @
171 PREINIT:
172 int i;
173 char **argv;
174 CODE:
175 rrdcode(rrd_update);
176 RETVAL = 1;
177 OUTPUT:
178 RETVAL
180 int
181 rrd_tune(...)
182 PROTOTYPE: @
183 PREINIT:
184 int i;
185 char **argv;
186 CODE:
187 rrdcode(rrd_tune);
188 RETVAL = 1;
189 OUTPUT:
190 RETVAL
192 SV *
193 rrd_graph(...)
194 PROTOTYPE: @
195 PREINIT:
196 char **calcpr=NULL;
197 int i,xsize,ysize;
198 double ymin,ymax;
199 char **argv;
200 AV *retar;
201 PPCODE:
202 argv = (char **) malloc((items+1)*sizeof(char *));
203 argv[0] = "dummy";
204 for (i = 0; i < items; i++) {
205 STRLEN len;
206 char *handle = SvPV(ST(i),len);
207 /* actually copy the data to make sure possible modifications
208 on the argv data does not backfire into perl */
209 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
210 strcpy(argv[i+1],handle);
211 }
212 rrd_clear_error();
213 rrd_graph(items+1,argv,&calcpr,&xsize,&ysize,NULL,&ymin,&ymax);
214 for (i=0; i < items; i++) {
215 free(argv[i+1]);
216 }
217 free(argv);
219 if (rrd_test_error()) {
220 if(calcpr)
221 for(i=0;calcpr[i];i++)
222 rrd_freemem(calcpr[i]);
223 XSRETURN_UNDEF;
224 }
225 retar=newAV();
226 if(calcpr){
227 for(i=0;calcpr[i];i++){
228 av_push(retar,newSVpv(calcpr[i],0));
229 rrd_freemem(calcpr[i]);
230 }
231 rrd_freemem(calcpr);
232 }
233 EXTEND(sp,4);
234 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
235 PUSHs(sv_2mortal(newSViv(xsize)));
236 PUSHs(sv_2mortal(newSViv(ysize)));
238 SV *
239 rrd_fetch(...)
240 PROTOTYPE: @
241 PREINIT:
242 time_t start,end;
243 unsigned long step, ds_cnt,i,ii;
244 rrd_value_t *data,*datai;
245 char **argv;
246 char **ds_namv;
247 AV *retar,*line,*names;
248 PPCODE:
249 argv = (char **) malloc((items+1)*sizeof(char *));
250 argv[0] = "dummy";
251 for (i = 0; i < items; i++) {
252 STRLEN len;
253 char *handle= SvPV(ST(i),len);
254 /* actually copy the data to make sure possible modifications
255 on the argv data does not backfire into perl */
256 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
257 strcpy(argv[i+1],handle);
258 }
259 rrd_clear_error();
260 rrd_fetch(items+1,argv,&start,&end,&step,&ds_cnt,&ds_namv,&data);
261 for (i=0; i < items; i++) {
262 free(argv[i+1]);
263 }
264 free(argv);
265 if (rrd_test_error()) XSRETURN_UNDEF;
266 /* convert the ds_namv into perl format */
267 names=newAV();
268 for (ii = 0; ii < ds_cnt; ii++){
269 av_push(names,newSVpv(ds_namv[ii],0));
270 rrd_freemem(ds_namv[ii]);
271 }
272 rrd_freemem(ds_namv);
273 /* convert the data array into perl format */
274 datai=data;
275 retar=newAV();
276 for (i = start+step; i <= end; i += step){
277 line = newAV();
278 for (ii = 0; ii < ds_cnt; ii++){
279 av_push(line,(isnan(*datai) ? &PL_sv_undef : newSVnv(*datai)));
280 datai++;
281 }
282 av_push(retar,newRV_noinc((SV*)line));
283 }
284 rrd_freemem(data);
285 EXTEND(sp,5);
286 PUSHs(sv_2mortal(newSViv(start+step)));
287 PUSHs(sv_2mortal(newSViv(step)));
288 PUSHs(sv_2mortal(newRV_noinc((SV*)names)));
289 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
291 SV *
292 rrd_times(start, end)
293 char *start
294 char *end
295 PREINIT:
296 rrd_time_value_t start_tv, end_tv;
297 char *parsetime_error = NULL;
298 time_t start_tmp, end_tmp;
299 PPCODE:
300 rrd_clear_error();
301 if ((parsetime_error = rrd_parsetime(start, &start_tv))) {
302 rrd_set_error("start time: %s", parsetime_error);
303 XSRETURN_UNDEF;
304 }
305 if ((parsetime_error = rrd_parsetime(end, &end_tv))) {
306 rrd_set_error("end time: %s", parsetime_error);
307 XSRETURN_UNDEF;
308 }
309 if (rrd_proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) {
310 XSRETURN_UNDEF;
311 }
312 EXTEND(sp,2);
313 PUSHs(sv_2mortal(newSVuv(start_tmp)));
314 PUSHs(sv_2mortal(newSVuv(end_tmp)));
316 int
317 rrd_xport(...)
318 PROTOTYPE: @
319 PREINIT:
320 time_t start,end;
321 int xsize;
322 unsigned long step, col_cnt,row_cnt,i,ii;
323 rrd_value_t *data,*ptr;
324 char **argv,**legend_v;
325 AV *retar,*line,*names;
326 PPCODE:
327 argv = (char **) malloc((items+1)*sizeof(char *));
328 argv[0] = "dummy";
329 for (i = 0; i < items; i++) {
330 STRLEN len;
331 char *handle = SvPV(ST(i),len);
332 /* actually copy the data to make sure possible modifications
333 on the argv data does not backfire into perl */
334 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
335 strcpy(argv[i+1],handle);
336 }
337 rrd_clear_error();
338 rrd_xport(items+1,argv,&xsize,&start,&end,&step,&col_cnt,&legend_v,&data);
339 for (i=0; i < items; i++) {
340 free(argv[i+1]);
341 }
342 free(argv);
343 if (rrd_test_error()) XSRETURN_UNDEF;
345 /* convert the legend_v into perl format */
346 names=newAV();
347 for (ii = 0; ii < col_cnt; ii++){
348 av_push(names,newSVpv(legend_v[ii],0));
349 rrd_freemem(legend_v[ii]);
350 }
351 rrd_freemem(legend_v);
353 /* convert the data array into perl format */
354 ptr=data;
355 retar=newAV();
356 for (i = start+step; i <= end; i += step){
357 line = newAV();
358 for (ii = 0; ii < col_cnt; ii++){
359 av_push(line,(isnan(*ptr) ? &PL_sv_undef : newSVnv(*ptr)));
360 ptr++;
361 }
362 av_push(retar,newRV_noinc((SV*)line));
363 }
364 rrd_freemem(data);
366 EXTEND(sp,7);
367 PUSHs(sv_2mortal(newSViv(start+step)));
368 PUSHs(sv_2mortal(newSViv(end)));
369 PUSHs(sv_2mortal(newSViv(step)));
370 PUSHs(sv_2mortal(newSViv(col_cnt)));
371 PUSHs(sv_2mortal(newRV_noinc((SV*)names)));
372 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
374 SV*
375 rrd_info(...)
376 PROTOTYPE: @
377 PREINIT:
378 rrd_info_t *data,*save;
379 int i;
380 char **argv;
381 HV *hash;
382 CODE:
383 rrdinfocode(rrd_info);
384 OUTPUT:
385 RETVAL
387 SV*
388 rrd_updatev(...)
389 PROTOTYPE: @
390 PREINIT:
391 rrd_info_t *data,*save;
392 int i;
393 char **argv;
394 HV *hash;
395 CODE:
396 rrdinfocode(rrd_update_v);
397 OUTPUT:
398 RETVAL
400 SV*
401 rrd_graphv(...)
402 PROTOTYPE: @
403 PREINIT:
404 rrd_info_t *data,*save;
405 int i;
406 char **argv;
407 HV *hash;
408 CODE:
409 rrdinfocode(rrd_graph_v);
410 OUTPUT:
411 RETVAL
413 int
414 rrd_dump(...)
415 PROTOTYPE: @
416 PREINIT:
417 int i;
418 char **argv;
419 CODE:
420 rrdcode(rrd_dump);
421 RETVAL = 1;
422 OUTPUT:
423 RETVAL
425 int
426 rrd_restore(...)
427 PROTOTYPE: @
428 PREINIT:
429 int i;
430 char **argv;
431 CODE:
432 rrdcode(rrd_restore);
433 RETVAL = 1;
434 OUTPUT:
435 RETVAL
437 #ifndef WIN32
438 int
439 rrd_flushcached(...)
440 PROTOTYPE: @
441 PREINIT:
442 int i;
443 char **argv;
444 CODE:
445 rrdcode(rrd_flushcached);
446 OUTPUT:
447 RETVAL
449 #endif