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