X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=bindings%2Fperl-shared%2FRRDs.xs;h=830a779d5f0f090c395cfeed3c0a445aa0b8b4f2;hp=d8eef7e07a6c4325abd049c9fcfba033119a22ce;hb=b0a526a0bcba4a883645db7c228f905c3906be77;hpb=5837606887a6d81e8b1f7588525cb1c8783fb62b diff --git a/bindings/perl-shared/RRDs.xs b/bindings/perl-shared/RRDs.xs index d8eef7e..830a779 100644 --- a/bindings/perl-shared/RRDs.xs +++ b/bindings/perl-shared/RRDs.xs @@ -10,12 +10,27 @@ extern "C" { } #endif -#include "../src/rrd_tool.h" - -/* perl 5.004 compatibility */ -#if PERLPATCHLEVEL < 5 -#define PL_sv_undef sv_undef +/* + * rrd_tool.h includes config.h, but at least on Ubuntu Breezy Badger + * 5.10 with gcc 4.0.2, the C preprocessor picks up Perl's config.h + * which is included from the Perl includes and never reads rrdtool's + * config.h. Without including rrdtool's config.h, this module does + * not compile, so include it here with an explicit path. + * + * Because rrdtool's config.h redefines VERSION which is originally + * set via Perl's Makefile.PL and passed down to the C compiler's + * command line, save the original value and reset it after the + * includes. + */ +#define VERSION_SAVED VERSION +#undef VERSION +#ifndef WIN32 +#include "../../rrd_config.h" #endif +#include "../../src/rrd_tool.h" +#undef VERSION +#define VERSION VERSION_SAVED +#undef VERSION_SAVED #define rrdcode(name) \ argv = (char **) malloc((items+1)*sizeof(char *));\ @@ -28,7 +43,6 @@ extern "C" { argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char)); \ strcpy(argv[i+1],handle); \ } \ - optind=0; opterr=0; \ rrd_clear_error();\ RETVAL=name(items+1,argv); \ for (i=0; i < items; i++) {\ @@ -38,12 +52,65 @@ extern "C" { \ if (rrd_test_error()) XSRETURN_UNDEF; +#define hvs(VAL) hv_store_ent(hash, sv_2mortal(newSVpv(data->key,0)),VAL,0) +#define rrdinfocode(name) \ + /* prepare argument list */ \ + argv = (char **) malloc((items+1)*sizeof(char *)); \ + argv[0] = "dummy"; \ + for (i = 0; i < items; i++) { \ + STRLEN len; \ + char *handle= SvPV(ST(i),len); \ + /* actually copy the data to make sure possible modifications \ + on the argv data does not backfire into perl */ \ + argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char)); \ + strcpy(argv[i+1],handle); \ + } \ + rrd_clear_error(); \ + data=name(items+1, argv); \ + for (i=0; i < items; i++) { \ + free(argv[i+1]); \ + } \ + free(argv); \ + if (rrd_test_error()) XSRETURN_UNDEF; \ + hash = newHV(); \ + save=data; \ + while (data) { \ + /* the newSV will get copied by hv so we create it as a mortal \ + to make sure it does not keep hanging round after the fact */ \ + switch (data->type) { \ + case RD_I_VAL: \ + if (isnan(data->value.u_val)) \ + hvs(newSV(0)); \ + else \ + hvs(newSVnv(data->value.u_val)); \ + break; \ + case RD_I_INT: \ + hvs(newSViv(data->value.u_int)); \ + break; \ + case RD_I_CNT: \ + hvs(newSViv(data->value.u_cnt)); \ + break; \ + case RD_I_STR: \ + hvs(newSVpv(data->value.u_str,0)); \ + break; \ + case RD_I_BLO: \ + hvs(newSVpv(data->value.u_blo.ptr,data->value.u_blo.size)); \ + break; \ + } \ + data = data->next; \ + } \ + rrd_info_free(save); \ + RETVAL = newRV_noinc((SV*)hash); + +/* + * should not be needed if libc is linked (see ntmake.pl) #ifdef WIN32 #define free free #define malloc malloc #define realloc realloc -#endif /*WIN32*/ +#endif +*/ MODULE = RRDs PACKAGE = RRDs PREFIX = rrd_ @@ -55,7 +122,6 @@ BOOT: #ifdef MUST_DISABLE_FPMASK fpsetmask(0); #endif - SV* rrd_error() @@ -65,7 +131,6 @@ rrd_error() OUTPUT: RETVAL - int rrd_last(...) PROTOTYPE: @ @@ -77,6 +142,16 @@ rrd_last(...) OUTPUT: RETVAL +int +rrd_first(...) + PROTOTYPE: @ + PREINIT: + int i; + char **argv; + CODE: + rrdcode(rrd_first); + OUTPUT: + RETVAL int rrd_create(...) @@ -90,7 +165,6 @@ rrd_create(...) OUTPUT: RETVAL - int rrd_update(...) PROTOTYPE: @ @@ -103,7 +177,6 @@ rrd_update(...) OUTPUT: RETVAL - int rrd_tune(...) PROTOTYPE: @ @@ -116,13 +189,13 @@ rrd_tune(...) OUTPUT: RETVAL - -void +SV * rrd_graph(...) PROTOTYPE: @ PREINIT: - char **calcpr; + char **calcpr=NULL; int i,xsize,ysize; + double ymin,ymax; char **argv; AV *retar; PPCODE: @@ -136,9 +209,8 @@ rrd_graph(...) argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char)); strcpy(argv[i+1],handle); } - optind=0; opterr=0; rrd_clear_error(); - rrd_graph(items+1,argv,&calcpr,&xsize,&ysize); + rrd_graph(items+1,argv,&calcpr,&xsize,&ysize,NULL,&ymin,&ymax); for (i=0; i < items; i++) { free(argv[i+1]); } @@ -147,23 +219,23 @@ rrd_graph(...) if (rrd_test_error()) { if(calcpr) for(i=0;calcpr[i];i++) - free(calcpr[i]); + rrd_freemem(calcpr[i]); XSRETURN_UNDEF; } retar=newAV(); if(calcpr){ for(i=0;calcpr[i];i++){ av_push(retar,newSVpv(calcpr[i],0)); - free(calcpr[i]); + rrd_freemem(calcpr[i]); } - free(calcpr); + rrd_freemem(calcpr); } EXTEND(sp,4); PUSHs(sv_2mortal(newRV_noinc((SV*)retar))); PUSHs(sv_2mortal(newSViv(xsize))); PUSHs(sv_2mortal(newSViv(ysize))); -void +SV * rrd_fetch(...) PROTOTYPE: @ PREINIT: @@ -184,7 +256,6 @@ rrd_fetch(...) argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char)); strcpy(argv[i+1],handle); } - optind=0; opterr=0; rrd_clear_error(); rrd_fetch(items+1,argv,&start,&end,&step,&ds_cnt,&ds_namv,&data); for (i=0; i < items; i++) { @@ -196,85 +267,183 @@ rrd_fetch(...) names=newAV(); for (ii = 0; ii < ds_cnt; ii++){ av_push(names,newSVpv(ds_namv[ii],0)); - free(ds_namv[ii]); + rrd_freemem(ds_namv[ii]); } - free(ds_namv); + rrd_freemem(ds_namv); /* convert the data array into perl format */ datai=data; retar=newAV(); - for (i = start; i <= end; i += step){ + for (i = start+step; i <= end; i += step){ line = newAV(); for (ii = 0; ii < ds_cnt; ii++){ - av_push(line,(isnan(*datai) ? &PL_sv_undef : newSVnv(*datai))); + av_push(line,(isnan(*datai) ? newSV(0) : newSVnv(*datai))); datai++; } av_push(retar,newRV_noinc((SV*)line)); } - free(data); + rrd_freemem(data); EXTEND(sp,5); - PUSHs(sv_2mortal(newSViv(start))); + PUSHs(sv_2mortal(newSViv(start+step))); PUSHs(sv_2mortal(newSViv(step))); PUSHs(sv_2mortal(newRV_noinc((SV*)names))); PUSHs(sv_2mortal(newRV_noinc((SV*)retar))); +SV * +rrd_times(start, end) + char *start + char *end + PREINIT: + rrd_time_value_t start_tv, end_tv; + char *parsetime_error = NULL; + time_t start_tmp, end_tmp; + PPCODE: + rrd_clear_error(); + if ((parsetime_error = rrd_parsetime(start, &start_tv))) { + rrd_set_error("start time: %s", parsetime_error); + XSRETURN_UNDEF; + } + if ((parsetime_error = rrd_parsetime(end, &end_tv))) { + rrd_set_error("end time: %s", parsetime_error); + XSRETURN_UNDEF; + } + if (rrd_proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) { + XSRETURN_UNDEF; + } + EXTEND(sp,2); + PUSHs(sv_2mortal(newSVuv(start_tmp))); + PUSHs(sv_2mortal(newSVuv(end_tmp))); -SV* -rrd_info(...) +int +rrd_xport(...) PROTOTYPE: @ PREINIT: - info_t *data,*save; - int i; - char **argv; - HV *hash; - CODE: - /* prepare argument list */ + time_t start,end; + int xsize; + unsigned long step, col_cnt,row_cnt,i,ii; + rrd_value_t *data,*ptr; + char **argv,**legend_v; + AV *retar,*line,*names; + PPCODE: argv = (char **) malloc((items+1)*sizeof(char *)); argv[0] = "dummy"; for (i = 0; i < items; i++) { STRLEN len; - char *handle= SvPV(ST(i),len); + char *handle = SvPV(ST(i),len); /* actually copy the data to make sure possible modifications on the argv data does not backfire into perl */ argv[i+1] = (char *) malloc((strlen(handle)+1)*sizeof(char)); strcpy(argv[i+1],handle); } - optind=0; opterr=0; - rrd_clear_error(); - data=rrd_info(items+1, argv); - for (i=0; i < items; i++) { + rrd_clear_error(); + rrd_xport(items+1,argv,&xsize,&start,&end,&step,&col_cnt,&legend_v,&data); + for (i=0; i < items; i++) { free(argv[i+1]); } free(argv); - if (rrd_test_error()) XSRETURN_UNDEF; - hash = newHV(); - while (data) { - save=data; - /* the newSV will get copied by hv so we create it as a mortal to make sure - it does not keep hanging round after the fact */ -#define hvs(VAL) hv_store_ent(hash, sv_2mortal(newSVpv(data->key,0)),VAL,0) - switch (data->type) { - case RD_I_VAL: - if (isnan(data->value.u_val)) - hvs(&PL_sv_undef); - else - hvs(newSVnv(data->value.u_val)); - break; - case RD_I_CNT: - hvs(newSViv(data->value.u_cnt)); - break; - case RD_I_STR: - hvs(newSVpv(data->value.u_str,0)); - free(data->value.u_str); - break; - } -#undefine hvs - free(data->key); - data = data->next; - free(save); + if (rrd_test_error()) XSRETURN_UNDEF; + + /* convert the legend_v into perl format */ + names=newAV(); + for (ii = 0; ii < col_cnt; ii++){ + av_push(names,newSVpv(legend_v[ii],0)); + rrd_freemem(legend_v[ii]); + } + rrd_freemem(legend_v); + + /* convert the data array into perl format */ + ptr=data; + retar=newAV(); + for (i = start+step; i <= end; i += step){ + line = newAV(); + for (ii = 0; ii < col_cnt; ii++){ + av_push(line,(isnan(*ptr) ? newSV(0) : newSVnv(*ptr))); + ptr++; + } + av_push(retar,newRV_noinc((SV*)line)); } - free(data); - RETVAL = newRV_noinc((SV*)hash); + rrd_freemem(data); + + EXTEND(sp,7); + PUSHs(sv_2mortal(newSViv(start+step))); + PUSHs(sv_2mortal(newSViv(end))); + PUSHs(sv_2mortal(newSViv(step))); + PUSHs(sv_2mortal(newSViv(col_cnt))); + PUSHs(sv_2mortal(newRV_noinc((SV*)names))); + PUSHs(sv_2mortal(newRV_noinc((SV*)retar))); + +SV* +rrd_info(...) + PROTOTYPE: @ + PREINIT: + rrd_info_t *data,*save; + int i; + char **argv; + HV *hash; + CODE: + rrdinfocode(rrd_info); + OUTPUT: + RETVAL + +SV* +rrd_updatev(...) + PROTOTYPE: @ + PREINIT: + rrd_info_t *data,*save; + int i; + char **argv; + HV *hash; + CODE: + rrdinfocode(rrd_update_v); + OUTPUT: + RETVAL + +SV* +rrd_graphv(...) + PROTOTYPE: @ + PREINIT: + rrd_info_t *data,*save; + int i; + char **argv; + HV *hash; + CODE: + rrdinfocode(rrd_graph_v); + OUTPUT: + RETVAL + +int +rrd_dump(...) + PROTOTYPE: @ + PREINIT: + int i; + char **argv; + CODE: + rrdcode(rrd_dump); + RETVAL = 1; OUTPUT: - RETVAL + RETVAL + +int +rrd_restore(...) + PROTOTYPE: @ + PREINIT: + int i; + char **argv; + CODE: + rrdcode(rrd_restore); + RETVAL = 1; + OUTPUT: + RETVAL +#ifndef WIN32 +int +rrd_flushcached(...) + PROTOTYPE: @ + PREINIT: + int i; + char **argv; + CODE: + rrdcode(rrd_flushcached); + OUTPUT: + RETVAL +#endif