1 #ifdef __cplusplus
2 extern "C" {
3 #endif
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "XSUB.h"
8 #include <time.h>
10 #ifdef __cplusplus
11 }
12 #endif
14 #include "../../src/rrd_tool.h"
16 /* perl 5.004 compatibility */
17 #if PERLPATCHLEVEL < 5
18 #define PL_sv_undef sv_undef
19 #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 /*
43 * should not be needed if libc is linked (see ntmake.pl)
44 #ifdef WIN32
45 #define free free
46 #define malloc malloc
47 #define realloc realloc
48 #endif
49 */
52 MODULE = RRDs PACKAGE = RRDs PREFIX = rrd_
54 BOOT:
55 #ifdef MUST_DISABLE_SIGFPE
56 signal(SIGFPE,SIG_IGN);
57 #endif
58 #ifdef MUST_DISABLE_FPMASK
59 fpsetmask(0);
60 #endif
63 SV*
64 rrd_error()
65 CODE:
66 if (! rrd_test_error()) XSRETURN_UNDEF;
67 RETVAL = newSVpv(rrd_get_error(),0);
68 OUTPUT:
69 RETVAL
72 int
73 rrd_last(...)
74 PROTOTYPE: @
75 PREINIT:
76 int i;
77 char **argv;
78 CODE:
79 rrdcode(rrd_last);
80 OUTPUT:
81 RETVAL
84 int
85 rrd_create(...)
86 PROTOTYPE: @
87 PREINIT:
88 int i;
89 char **argv;
90 CODE:
91 rrdcode(rrd_create);
92 RETVAL = 1;
93 OUTPUT:
94 RETVAL
97 int
98 rrd_update(...)
99 PROTOTYPE: @
100 PREINIT:
101 int i;
102 char **argv;
103 CODE:
104 rrdcode(rrd_update);
105 RETVAL = 1;
106 OUTPUT:
107 RETVAL
110 int
111 rrd_tune(...)
112 PROTOTYPE: @
113 PREINIT:
114 int i;
115 char **argv;
116 CODE:
117 rrdcode(rrd_tune);
118 RETVAL = 1;
119 OUTPUT:
120 RETVAL
123 void
124 rrd_graph(...)
125 PROTOTYPE: @
126 PREINIT:
127 char **calcpr;
128 int i,xsize,ysize;
129 char **argv;
130 AV *retar;
131 PPCODE:
132 argv = (char **) malloc((items+1)*sizeof(char *));
133 argv[0] = "dummy";
134 for (i = 0; i < items; i++) {
135 STRLEN len;
136 char *handle = SvPV(ST(i),len);
137 /* actually copy the data to make sure possible modifications
138 on the argv data does not backfire into perl */
139 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
140 strcpy(argv[i+1],handle);
141 }
142 optind=0; opterr=0;
143 rrd_clear_error();
144 tzset();
145 rrd_graph(items+1,argv,&calcpr,&xsize,&ysize);
146 for (i=0; i < items; i++) {
147 free(argv[i+1]);
148 }
149 free(argv);
151 if (rrd_test_error()) {
152 if(calcpr)
153 for(i=0;calcpr[i];i++)
154 free(calcpr[i]);
155 XSRETURN_UNDEF;
156 }
157 retar=newAV();
158 if(calcpr){
159 for(i=0;calcpr[i];i++){
160 av_push(retar,newSVpv(calcpr[i],0));
161 free(calcpr[i]);
162 }
163 free(calcpr);
164 }
165 EXTEND(sp,4);
166 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
167 PUSHs(sv_2mortal(newSViv(xsize)));
168 PUSHs(sv_2mortal(newSViv(ysize)));
170 void
171 rrd_fetch(...)
172 PROTOTYPE: @
173 PREINIT:
174 time_t start,end;
175 unsigned long step, ds_cnt,i,ii;
176 rrd_value_t *data,*datai;
177 char **argv;
178 char **ds_namv;
179 AV *retar,*line,*names;
180 PPCODE:
181 argv = (char **) malloc((items+1)*sizeof(char *));
182 argv[0] = "dummy";
183 for (i = 0; i < items; i++) {
184 STRLEN len;
185 char *handle= SvPV(ST(i),len);
186 /* actually copy the data to make sure possible modifications
187 on the argv data does not backfire into perl */
188 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
189 strcpy(argv[i+1],handle);
190 }
191 optind=0; opterr=0;
192 rrd_clear_error();
193 rrd_fetch(items+1,argv,&start,&end,&step,&ds_cnt,&ds_namv,&data);
194 for (i=0; i < items; i++) {
195 free(argv[i+1]);
196 }
197 free(argv);
198 if (rrd_test_error()) XSRETURN_UNDEF;
199 /* convert the ds_namv into perl format */
200 names=newAV();
201 for (ii = 0; ii < ds_cnt; ii++){
202 av_push(names,newSVpv(ds_namv[ii],0));
203 free(ds_namv[ii]);
204 }
205 free(ds_namv);
206 /* convert the data array into perl format */
207 datai=data;
208 retar=newAV();
209 for (i = start; i <= end; i += step){
210 line = newAV();
211 for (ii = 0; ii < ds_cnt; ii++){
212 av_push(line,(isnan(*datai) ? &PL_sv_undef : newSVnv(*datai)));
213 datai++;
214 }
215 av_push(retar,newRV_noinc((SV*)line));
216 }
217 free(data);
218 EXTEND(sp,5);
219 PUSHs(sv_2mortal(newSViv(start)));
220 PUSHs(sv_2mortal(newSViv(step)));
221 PUSHs(sv_2mortal(newRV_noinc((SV*)names)));
222 PUSHs(sv_2mortal(newRV_noinc((SV*)retar)));
225 SV*
226 rrd_info(...)
227 PROTOTYPE: @
228 PREINIT:
229 info_t *data,*save;
230 int i;
231 char **argv;
232 HV *hash;
233 CODE:
234 /* prepare argument list */
235 argv = (char **) malloc((items+1)*sizeof(char *));
236 argv[0] = "dummy";
237 for (i = 0; i < items; i++) {
238 STRLEN len;
239 char *handle= SvPV(ST(i),len);
240 /* actually copy the data to make sure possible modifications
241 on the argv data does not backfire into perl */
242 argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char));
243 strcpy(argv[i+1],handle);
244 }
245 optind=0; opterr=0;
246 rrd_clear_error();
247 data=rrd_info(items+1, argv);
248 for (i=0; i < items; i++) {
249 free(argv[i+1]);
250 }
251 free(argv);
252 if (rrd_test_error()) XSRETURN_UNDEF;
253 hash = newHV();
254 while (data) {
255 save=data;
256 /* the newSV will get copied by hv so we create it as a mortal to make sure
257 it does not keep hanging round after the fact */
258 #define hvs(VAL) hv_store_ent(hash, sv_2mortal(newSVpv(data->key,0)),VAL,0)
259 switch (data->type) {
260 case RD_I_VAL:
261 if (isnan(data->value.u_val))
262 hvs(&PL_sv_undef);
263 else
264 hvs(newSVnv(data->value.u_val));
265 break;
266 case RD_I_CNT:
267 hvs(newSViv(data->value.u_cnt));
268 break;
269 case RD_I_STR:
270 hvs(newSVpv(data->value.u_str,0));
271 free(data->value.u_str);
272 break;
273 }
274 #undefine hvs
275 free(data->key);
276 data = data->next;
277 free(save);
278 }
279 free(data);
280 RETVAL = newRV_noinc((SV*)hash);
281 OUTPUT:
282 RETVAL