Alternate update interface, updatev. Returns info about CDPs written to disk as resul...
[rrdtool.git] / bindings / perl-shared / RRDs.xs
index 4d871e9..474c9c4 100644 (file)
@@ -17,6 +17,7 @@ extern "C" {
 #define PL_sv_undef sv_undef
 #endif
 
+
 #define rrdcode(name) \
                argv = (char **) malloc((items+1)*sizeof(char *));\
                argv[0] = "dummy";\
@@ -38,6 +39,58 @@ 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); \
+               } \
+               optind=0; opterr=0; \
+                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(); \
+                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 */ \
+                   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_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)); \
+                       rrd_freemem(data->value.u_str); \
+                       break; \
+                   } \
+                   rrd_freemem(data->key); \
+                   data = data->next; \
+                   rrd_freemem(save); \
+                   } \
+            rrd_freemem(data); \
+            RETVAL = newRV_noinc((SV*)hash);
+
 /*
  * should not be needed if libc is linked (see ntmake.pl)
 #ifdef WIN32
@@ -149,16 +202,16 @@ 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)));
@@ -198,13 +251,13 @@ 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)));
@@ -212,71 +265,96 @@ rrd_fetch(...)
                        }
                        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_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]);
                }
-                free(data);
-                RETVAL = newRV_noinc((SV*)hash);
-       OUTPUT:
-               RETVAL
+               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) ? &PL_sv_undef : newSVnv(*ptr)));
+                         ptr++;
+                       }
+                       av_push(retar,newRV_noinc((SV*)line));
+               }
+               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:
+               info_t *data,*save;
+                int i;
+                char **argv;
+               HV *hash;
+       CODE:
+               rrdinfocode(rrd_info);  
+    OUTPUT:
+          RETVAL
 
+SV*
+rrd_updatev(...)
+       PROTOTYPE: @    
+       PREINIT:
+               info_t *data,*save;
+                int i;
+                char **argv;
+               HV *hash;
+       CODE:
+               rrdinfocode(rrd_update_v);      
+    OUTPUT:
+          RETVAL