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