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