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