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 save=data; \
82 while (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 break; \
101 case RD_I_BLO: \
102 hvs(newSVpv(data->value.u_blo.ptr,data->value.u_blo.size)); \
103 break; \
104 } \
105 data = data->next; \
106 } \
107 rrd_info_free(save); \
108 RETVAL = newRV_noinc((SV*)hash);
110 /*
111 * should not be needed if libc is linked (see ntmake.pl)
112 #ifdef WIN32
113 #define free free
114 #define malloc malloc
115 #define realloc realloc
116 #endif
117 */
120 MODULE = RRDs PACKAGE = RRDs PREFIX = rrd_
122 BOOT:
123 #ifdef MUST_DISABLE_SIGFPE
124 signal(SIGFPE,SIG_IGN);
125 #endif
126 #ifdef MUST_DISABLE_FPMASK
127 fpsetmask(0);
128 #endif
131 SV*
132 rrd_error()
133 CODE:
134 if (! rrd_test_error()) XSRETURN_UNDEF;
135 RETVAL = newSVpv(rrd_get_error(),0);
136 OUTPUT:
137 RETVAL
140 int
141 rrd_last(...)
142 PROTOTYPE: @
143 PREINIT:
144 int i;
145 char **argv;
146 CODE:
147 rrdcode(rrd_last);
148 OUTPUT:
149 RETVAL
151 int
152 rrd_first(...)
153 PROTOTYPE: @
154 PREINIT:
155 int i;
156 char **argv;
157 CODE:
158 rrdcode(rrd_first);
159 OUTPUT:
160 RETVAL
163 int
164 rrd_create(...)
165 PROTOTYPE: @
166 PREINIT:
167 int i;
168 char **argv;
169 CODE:
170 rrdcode(rrd_create);
171 RETVAL = 1;
172 OUTPUT:
173 RETVAL
176 int
177 rrd_update(...)
178 PROTOTYPE: @
179 PREINIT:
180 int i;
181 char **argv;
182 CODE:
183 rrdcode(rrd_update);
184 RETVAL = 1;
185 OUTPUT:
186 RETVAL
189 int
190 rrd_tune(...)
191 PROTOTYPE: @
192 PREINIT:
193 int i;
194 char **argv;
195 CODE:
196 rrdcode(rrd_tune);
197 RETVAL = 1;
198 OUTPUT:
199 RETVAL
202 SV *
203 rrd_graph(...)
204 PROTOTYPE: @
205 PREINIT:
206 char **calcpr=NULL;
207 int i,xsize,ysize;
208 double ymin,ymax;
209 char **argv;
210 AV *retar;
211 PPCODE:
212 argv = (char **) malloc((items+1)*sizeof(char *));
213 argv[0] = "dummy";
214 for (i = 0; i < items; i++) {
215 STRLEN len;
216 char *handle = SvPV(ST(i),len);
217 /* actually copy the data to make sure possible modifications
218 on the argv data does not backfire into perl */
219 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
220 strcpy(argv[i+1],handle);
221 }
222 rrd_clear_error();
223 rrd_graph(items+1,argv,&calcpr,&xsize,&ysize,NULL,&ymin,&ymax);
224 for (i=0; i < items; i++) {
225 free(argv[i+1]);
226 }
227 free(argv);
229 if (rrd_test_error()) {
230 if(calcpr)
231 for(i=0;calcpr[i];i++)
232 rrd_freemem(calcpr[i]);
233 XSRETURN_UNDEF;
234 }
235 retar=newAV();
236 if(calcpr){
237 for(i=0;calcpr[i];i++){
238 av_push(retar,newSVpv(calcpr[i],0));
239 rrd_freemem(calcpr[i]);
240 }
241 rrd_freemem(calcpr);
242 }
243 EXTEND(sp,4);
244 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
245 PUSHs(sv_2mortal(newSViv(xsize)));
246 PUSHs(sv_2mortal(newSViv(ysize)));
248 SV *
249 rrd_fetch(...)
250 PROTOTYPE: @
251 PREINIT:
252 time_t start,end;
253 unsigned long step, ds_cnt,i,ii;
254 rrd_value_t *data,*datai;
255 char **argv;
256 char **ds_namv;
257 AV *retar,*line,*names;
258 PPCODE:
259 argv = (char **) malloc((items+1)*sizeof(char *));
260 argv[0] = "dummy";
261 for (i = 0; i < items; i++) {
262 STRLEN len;
263 char *handle= SvPV(ST(i),len);
264 /* actually copy the data to make sure possible modifications
265 on the argv data does not backfire into perl */
266 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
267 strcpy(argv[i+1],handle);
268 }
269 rrd_clear_error();
270 rrd_fetch(items+1,argv,&start,&end,&step,&ds_cnt,&ds_namv,&data);
271 for (i=0; i < items; i++) {
272 free(argv[i+1]);
273 }
274 free(argv);
275 if (rrd_test_error()) XSRETURN_UNDEF;
276 /* convert the ds_namv into perl format */
277 names=newAV();
278 for (ii = 0; ii < ds_cnt; ii++){
279 av_push(names,newSVpv(ds_namv[ii],0));
280 rrd_freemem(ds_namv[ii]);
281 }
282 rrd_freemem(ds_namv);
283 /* convert the data array into perl format */
284 datai=data;
285 retar=newAV();
286 for (i = start+step; i <= end; i += step){
287 line = newAV();
288 for (ii = 0; ii < ds_cnt; ii++){
289 av_push(line,(isnan(*datai) ? &PL_sv_undef : newSVnv(*datai)));
290 datai++;
291 }
292 av_push(retar,newRV_noinc((SV*)line));
293 }
294 rrd_freemem(data);
295 EXTEND(sp,5);
296 PUSHs(sv_2mortal(newSViv(start+step)));
297 PUSHs(sv_2mortal(newSViv(step)));
298 PUSHs(sv_2mortal(newRV_noinc((SV*)names)));
299 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
301 SV *
302 rrd_times(start, end)
303 char *start
304 char *end
305 PREINIT:
306 rrd_time_value_t start_tv, end_tv;
307 char *parsetime_error = NULL;
308 time_t start_tmp, end_tmp;
309 PPCODE:
310 rrd_clear_error();
311 if ((parsetime_error = rrd_parsetime(start, &start_tv))) {
312 rrd_set_error("start time: %s", parsetime_error);
313 XSRETURN_UNDEF;
314 }
315 if ((parsetime_error = rrd_parsetime(end, &end_tv))) {
316 rrd_set_error("end time: %s", parsetime_error);
317 XSRETURN_UNDEF;
318 }
319 if (rrd_proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) {
320 XSRETURN_UNDEF;
321 }
322 EXTEND(sp,2);
323 PUSHs(sv_2mortal(newSVuv(start_tmp)));
324 PUSHs(sv_2mortal(newSVuv(end_tmp)));
326 int
327 rrd_xport(...)
328 PROTOTYPE: @
329 PREINIT:
330 time_t start,end;
331 int xsize;
332 unsigned long step, col_cnt,row_cnt,i,ii;
333 rrd_value_t *data,*ptr;
334 char **argv,**legend_v;
335 AV *retar,*line,*names;
336 PPCODE:
337 argv = (char **) malloc((items+1)*sizeof(char *));
338 argv[0] = "dummy";
339 for (i = 0; i < items; i++) {
340 STRLEN len;
341 char *handle = SvPV(ST(i),len);
342 /* actually copy the data to make sure possible modifications
343 on the argv data does not backfire into perl */
344 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
345 strcpy(argv[i+1],handle);
346 }
347 rrd_clear_error();
348 rrd_xport(items+1,argv,&xsize,&start,&end,&step,&col_cnt,&legend_v,&data);
349 for (i=0; i < items; i++) {
350 free(argv[i+1]);
351 }
352 free(argv);
353 if (rrd_test_error()) XSRETURN_UNDEF;
355 /* convert the legend_v into perl format */
356 names=newAV();
357 for (ii = 0; ii < col_cnt; ii++){
358 av_push(names,newSVpv(legend_v[ii],0));
359 rrd_freemem(legend_v[ii]);
360 }
361 rrd_freemem(legend_v);
363 /* convert the data array into perl format */
364 ptr=data;
365 retar=newAV();
366 for (i = start+step; i <= end; i += step){
367 line = newAV();
368 for (ii = 0; ii < col_cnt; ii++){
369 av_push(line,(isnan(*ptr) ? &PL_sv_undef : newSVnv(*ptr)));
370 ptr++;
371 }
372 av_push(retar,newRV_noinc((SV*)line));
373 }
374 rrd_freemem(data);
376 EXTEND(sp,7);
377 PUSHs(sv_2mortal(newSViv(start+step)));
378 PUSHs(sv_2mortal(newSViv(end)));
379 PUSHs(sv_2mortal(newSViv(step)));
380 PUSHs(sv_2mortal(newSViv(col_cnt)));
381 PUSHs(sv_2mortal(newRV_noinc((SV*)names)));
382 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
384 SV*
385 rrd_info(...)
386 PROTOTYPE: @
387 PREINIT:
388 rrd_info_t *data,*save;
389 int i;
390 char **argv;
391 HV *hash;
392 CODE:
393 rrdinfocode(rrd_info);
394 OUTPUT:
395 RETVAL
397 SV*
398 rrd_updatev(...)
399 PROTOTYPE: @
400 PREINIT:
401 rrd_info_t *data,*save;
402 int i;
403 char **argv;
404 HV *hash;
405 CODE:
406 rrdinfocode(rrd_update_v);
407 OUTPUT:
408 RETVAL
410 SV*
411 rrd_graphv(...)
412 PROTOTYPE: @
413 PREINIT:
414 rrd_info_t *data,*save;
415 int i;
416 char **argv;
417 HV *hash;
418 CODE:
419 rrdinfocode(rrd_graph_v);
420 OUTPUT:
421 RETVAL
423 int
424 rrd_dump(...)
425 PROTOTYPE: @
426 PREINIT:
427 int i;
428 char **argv;
429 CODE:
430 rrdcode(rrd_dump);
431 RETVAL = 1;
432 OUTPUT:
433 RETVAL
435 int
436 rrd_restore(...)
437 PROTOTYPE: @
438 PREINIT:
439 int i;
440 char **argv;
441 CODE:
442 rrdcode(rrd_restore);
443 RETVAL = 1;
444 OUTPUT:
445 RETVAL
447 int
448 rrd_flushcached(...)
449 PROTOTYPE: @
450 PREINIT:
451 int i;
452 char **argv;
453 CODE:
454 rrdcode(rrd_flushcached);
455 OUTPUT:
456 RETVAL