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
136 int
137 rrd_create(...)
138 PROTOTYPE: @
139 PREINIT:
140 int i;
141 char **argv;
142 CODE:
143 rrdcode(rrd_create);
144 RETVAL = 1;
145 OUTPUT:
146 RETVAL
149 int
150 rrd_update(...)
151 PROTOTYPE: @
152 PREINIT:
153 int i;
154 char **argv;
155 CODE:
156 rrdcode(rrd_update);
157 RETVAL = 1;
158 OUTPUT:
159 RETVAL
162 int
163 rrd_tune(...)
164 PROTOTYPE: @
165 PREINIT:
166 int i;
167 char **argv;
168 CODE:
169 rrdcode(rrd_tune);
170 RETVAL = 1;
171 OUTPUT:
172 RETVAL
175 void
176 rrd_graph(...)
177 PROTOTYPE: @
178 PREINIT:
179 char **calcpr=NULL;
180 int i,xsize,ysize;
181 double ymin,ymax;
182 char **argv;
183 AV *retar;
184 PPCODE:
185 argv = (char **) malloc((items+1)*sizeof(char *));
186 argv[0] = "dummy";
187 for (i = 0; i < items; i++) {
188 STRLEN len;
189 char *handle = SvPV(ST(i),len);
190 /* actually copy the data to make sure possible modifications
191 on the argv data does not backfire into perl */
192 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
193 strcpy(argv[i+1],handle);
194 }
195 optind=0; opterr=0;
196 rrd_clear_error();
197 rrd_graph(items+1,argv,&calcpr,&xsize,&ysize,NULL,&ymin,&ymax);
198 for (i=0; i < items; i++) {
199 free(argv[i+1]);
200 }
201 free(argv);
203 if (rrd_test_error()) {
204 if(calcpr)
205 for(i=0;calcpr[i];i++)
206 rrd_freemem(calcpr[i]);
207 XSRETURN_UNDEF;
208 }
209 retar=newAV();
210 if(calcpr){
211 for(i=0;calcpr[i];i++){
212 av_push(retar,newSVpv(calcpr[i],0));
213 rrd_freemem(calcpr[i]);
214 }
215 rrd_freemem(calcpr);
216 }
217 EXTEND(sp,4);
218 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
219 PUSHs(sv_2mortal(newSViv(xsize)));
220 PUSHs(sv_2mortal(newSViv(ysize)));
222 void
223 rrd_fetch(...)
224 PROTOTYPE: @
225 PREINIT:
226 time_t start,end;
227 unsigned long step, ds_cnt,i,ii;
228 rrd_value_t *data,*datai;
229 char **argv;
230 char **ds_namv;
231 AV *retar,*line,*names;
232 PPCODE:
233 argv = (char **) malloc((items+1)*sizeof(char *));
234 argv[0] = "dummy";
235 for (i = 0; i < items; i++) {
236 STRLEN len;
237 char *handle= SvPV(ST(i),len);
238 /* actually copy the data to make sure possible modifications
239 on the argv data does not backfire into perl */
240 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
241 strcpy(argv[i+1],handle);
242 }
243 optind=0; opterr=0;
244 rrd_clear_error();
245 rrd_fetch(items+1,argv,&start,&end,&step,&ds_cnt,&ds_namv,&data);
246 for (i=0; i < items; i++) {
247 free(argv[i+1]);
248 }
249 free(argv);
250 if (rrd_test_error()) XSRETURN_UNDEF;
251 /* convert the ds_namv into perl format */
252 names=newAV();
253 for (ii = 0; ii < ds_cnt; ii++){
254 av_push(names,newSVpv(ds_namv[ii],0));
255 rrd_freemem(ds_namv[ii]);
256 }
257 rrd_freemem(ds_namv);
258 /* convert the data array into perl format */
259 datai=data;
260 retar=newAV();
261 for (i = start+step; i <= end; i += step){
262 line = newAV();
263 for (ii = 0; ii < ds_cnt; ii++){
264 av_push(line,(isnan(*datai) ? &PL_sv_undef : newSVnv(*datai)));
265 datai++;
266 }
267 av_push(retar,newRV_noinc((SV*)line));
268 }
269 rrd_freemem(data);
270 EXTEND(sp,5);
271 PUSHs(sv_2mortal(newSViv(start+step)));
272 PUSHs(sv_2mortal(newSViv(step)));
273 PUSHs(sv_2mortal(newRV_noinc((SV*)names)));
274 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
276 void
277 rrd_times(start, end)
278 char *start
279 char *end
280 PREINIT:
281 struct rrd_time_value start_tv, end_tv;
282 char *parsetime_error = NULL;
283 time_t start_tmp, end_tmp;
284 PPCODE:
285 rrd_clear_error();
286 if( (parsetime_error = parsetime( start, &start_tv))) {
287 rrd_set_error( "start time: %s", parsetime_error);
288 XSRETURN_UNDEF;
289 }
290 if( (parsetime_error = parsetime( end, &end_tv))) {
291 rrd_set_error( "end time: %s", parsetime_error);
292 XSRETURN_UNDEF;
293 }
294 if( proc_start_end( &start_tv, &end_tv, &start_tmp, &end_tmp) == -1) {
295 XSRETURN_UNDEF;
296 }
297 EXTEND(sp,2);
298 PUSHs(sv_2mortal(newSVuv(start_tmp)));
299 PUSHs(sv_2mortal(newSVuv(end_tmp)));
301 int
302 rrd_xport(...)
303 PROTOTYPE: @
304 PREINIT:
305 time_t start,end;
306 int xsize;
307 unsigned long step, col_cnt,row_cnt,i,ii;
308 rrd_value_t *data,*ptr;
309 char **argv,**legend_v;
310 AV *retar,*line,*names;
311 PPCODE:
312 argv = (char **) malloc((items+1)*sizeof(char *));
313 argv[0] = "dummy";
314 for (i = 0; i < items; i++) {
315 STRLEN len;
316 char *handle = SvPV(ST(i),len);
317 /* actually copy the data to make sure possible modifications
318 on the argv data does not backfire into perl */
319 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
320 strcpy(argv[i+1],handle);
321 }
322 optind=0; opterr=0;
323 rrd_clear_error();
324 rrd_xport(items+1,argv,&xsize,&start,&end,&step,&col_cnt,&legend_v,&data);
325 for (i=0; i < items; i++) {
326 free(argv[i+1]);
327 }
328 free(argv);
329 if (rrd_test_error()) XSRETURN_UNDEF;
331 /* convert the legend_v into perl format */
332 names=newAV();
333 for (ii = 0; ii < col_cnt; ii++){
334 av_push(names,newSVpv(legend_v[ii],0));
335 rrd_freemem(legend_v[ii]);
336 }
337 rrd_freemem(legend_v);
339 /* convert the data array into perl format */
340 ptr=data;
341 retar=newAV();
342 for (i = start+step; i <= end; i += step){
343 line = newAV();
344 for (ii = 0; ii < col_cnt; ii++){
345 av_push(line,(isnan(*ptr) ? &PL_sv_undef : newSVnv(*ptr)));
346 ptr++;
347 }
348 av_push(retar,newRV_noinc((SV*)line));
349 }
350 rrd_freemem(data);
352 EXTEND(sp,7);
353 PUSHs(sv_2mortal(newSViv(start+step)));
354 PUSHs(sv_2mortal(newSViv(end)));
355 PUSHs(sv_2mortal(newSViv(step)));
356 PUSHs(sv_2mortal(newSViv(col_cnt)));
357 PUSHs(sv_2mortal(newRV_noinc((SV*)names)));
358 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
360 SV*
361 rrd_info(...)
362 PROTOTYPE: @
363 PREINIT:
364 info_t *data,*save;
365 int i;
366 char **argv;
367 HV *hash;
368 CODE:
369 rrdinfocode(rrd_info);
370 OUTPUT:
371 RETVAL
373 SV*
374 rrd_updatev(...)
375 PROTOTYPE: @
376 PREINIT:
377 info_t *data,*save;
378 int i;
379 char **argv;
380 HV *hash;
381 CODE:
382 rrdinfocode(rrd_update_v);
383 OUTPUT:
384 RETVAL
386 int
387 rrd_dump(...)
388 PROTOTYPE: @
389 PREINIT:
390 int i;
391 char **argv;
392 CODE:
393 rrdcode(rrd_dump);
394 RETVAL = 1;
395 OUTPUT:
396 RETVAL
398 int
399 rrd_restore(...)
400 PROTOTYPE: @
401 PREINIT:
402 int i;
403 char **argv;
404 CODE:
405 rrdcode(rrd_restore);
406 RETVAL = 1;
407 OUTPUT:
408 RETVAL