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