Code

implement CSV, TSC, SSV with JSON and XML as "graphics" formats for rrdgraph -- Marti...
[rrdtool.git] / src / rrd_graph.c
index b101b329388332d74209d3809431d938a7f57d67..240e96f7cb48e673f61a51afd1ba2f8165190059 100644 (file)
@@ -59,6 +59,8 @@ text_prop_t text_prop[] = {
     {5.5, RRD_DEFAULT_FONT,NULL} /* watermark */
 };
 
+char week_fmt[128] = "Week %V";
+
 xlab_t    xlab[] = {
     {0, 0, TMT_SECOND, 30, TMT_MINUTE, 5, TMT_MINUTE, 5, 0, "%H:%M"}
     ,
@@ -87,10 +89,9 @@ xlab_t    xlab[] = {
     ,
     {2400, 0, TMT_HOUR, 12, TMT_DAY, 1, TMT_DAY, 2, 24 * 3600, "%a"}
     ,
-    {3600, 0, TMT_DAY, 1, TMT_WEEK, 1, TMT_WEEK, 1, 7 * 24 * 3600, "Week %V"}
+    {3600, 0, TMT_DAY, 1, TMT_WEEK, 1, TMT_WEEK, 1, 7 * 24 * 3600, week_fmt}
     ,
-    {3 * 3600, 0, TMT_WEEK, 1, TMT_MONTH, 1, TMT_WEEK, 2, 7 * 24 * 3600,
-     "Week %V"}
+    {3 * 3600, 0, TMT_WEEK, 1, TMT_MONTH, 1, TMT_WEEK, 2, 7 * 24 * 3600, week_fmt}
     ,
     {6 * 3600, 0, TMT_MONTH, 1, TMT_MONTH, 1, TMT_MONTH, 1, 30 * 24 * 3600,
      "%b"}
@@ -255,6 +256,11 @@ enum gfx_if_en if_conv(
     conv_if(SVG, IF_SVG);
     conv_if(EPS, IF_EPS);
     conv_if(PDF, IF_PDF);
+    conv_if(XML, IF_XML);
+    conv_if(CSV, IF_CSV);
+    conv_if(TSV, IF_TSV);
+    conv_if(SSV, IF_SSV);
+    conv_if(JSON, IF_JSON);
 
     return (enum gfx_if_en)(-1);
 }
@@ -411,8 +417,11 @@ void auto_scale(
     }
 }
 
+/* power prefixes */
 
 static char si_symbol[] = {
+    'y',                /* 10e-24 Yocto */
+    'z',                /* 10e-21 Zepto */
     'a',                /* 10e-18 Atto */
     'f',                /* 10e-15 Femto */
     'p',                /* 10e-12 Pico */
@@ -426,8 +435,10 @@ static char si_symbol[] = {
     'T',                /* 10e12  Tera */
     'P',                /* 10e15  Peta */
     'E',                /* 10e18  Exa */
+    'Z',                /* 10e21  Zeta */
+    'Y'                 /* 10e24  Yotta */
 };
-static const int si_symbcenter = 6;
+static const int si_symbcenter = 8;
 
 /* find SI magnitude symbol for the numbers on the y-axis*/
 void si_unit(
@@ -894,11 +905,15 @@ int data_fetch(
                                 &im->gdes[i].ds_cnt,
                                 &im->gdes[i].ds_namv,
                                 &im->gdes[i].data)) == -1) {
-                    return -1;
-                }
+                    return -1;                      
+                }               
             }
             im->gdes[i].data_first = 1;
 
+            /* must reduce to at least im->step
+               otherwhise we end up with more data than we can handle in the 
+               chart and visibility of data will be random */            
+            im->gdes[i].step = max(im->gdes[i].step,im->step);
             if (ft_step < im->gdes[i].step) {
                 reduce_data(im->gdes[i].cf_reduce,
                             ft_step,
@@ -1780,6 +1795,7 @@ int leg_place(
                 prt_fctn != 'j' &&
                 prt_fctn != 'c' &&
                 prt_fctn != 'u' &&
+                prt_fctn != '.' &&
                 prt_fctn != 's' && prt_fctn != '\0' && prt_fctn != 'g') {
                 free(legspace);
                 rrd_set_error
@@ -1791,6 +1807,10 @@ int leg_place(
             if (prt_fctn == 'n') {
                 prt_fctn = 'l';
             }
+            /* \. is a null operation to allow strings ending in \x */
+            if (prt_fctn == '.') {
+                prt_fctn = '\0';
+            }
 
             /* remove exess space from the end of the legend for \g */
             while (prt_fctn == 'g' &&
@@ -1866,7 +1886,7 @@ int leg_place(
                     glue = 0;
                 }
                 if (prt_fctn == 'c')
-                    leg_x = (double)(legendwidth - fill) / 2.0;
+                    leg_x = border + (double)(legendwidth - fill) / 2.0;
                 if (prt_fctn == 'r')
                     leg_x = legendwidth - fill + border;
                 for (ii = mark; ii <= i; ii++) {
@@ -2937,6 +2957,7 @@ int graph_size_location(
         im->ximg = im->xsize;
         im->yimg = im->ysize;
         im->yorigin = im->ysize;
+        xtr(im, 0);
         ytr(im, DNAN);
         return 0;
     }
@@ -2968,7 +2989,7 @@ int graph_size_location(
     }
     else{
         // we have no title; get a little clearing from the top
-        Ytitle = 1.5 * Yspacing;
+        Ytitle = Yspacing;
     }
 
     if (elements) {
@@ -3062,7 +3083,7 @@ int graph_size_location(
 
             /* reserve space for padding below the graph */
         if (im->extra_flags & NOLEGEND) {
-            Ymain -= Yspacing;
+            Ymain -= 0.5*Yspacing;
         }
 
         if (im->watermark[0] != '\0') {
@@ -3122,7 +3143,7 @@ int graph_size_location(
         }
         /* reserve space for padding below the graph */
         if (im->extra_flags & NOLEGEND) {
-            im->yimg += Yspacing;
+            im->yimg += 0.5*Yspacing;
         }
 
         if (im->watermark[0] != '\0') {
@@ -3151,7 +3172,7 @@ int graph_size_location(
      */
     switch(im->legendposition){
         case NORTH:
-            im->xOriginTitle   = Xvertical + Xylabel + (im->xsize / 2);
+            im->xOriginTitle   = (im->ximg / 2);
             im->yOriginTitle   = 0;
 
             im->xOriginLegend  = 0;
@@ -3172,7 +3193,7 @@ int graph_size_location(
             break;
 
         case WEST:
-            im->xOriginTitle   = im->legendwidth + Xvertical + Xylabel + im->xsize / 2;
+            im->xOriginTitle   = im->legendwidth + im->xsize / 2;
             im->yOriginTitle   = 0;
 
             im->xOriginLegend  = 0;
@@ -3193,7 +3214,7 @@ int graph_size_location(
             break;
 
         case SOUTH:
-            im->xOriginTitle   = Xvertical + Xylabel + im->xsize / 2;
+            im->xOriginTitle   = im->ximg / 2;
             im->yOriginTitle   = 0;
 
             im->xOriginLegend  = 0;
@@ -3214,7 +3235,7 @@ int graph_size_location(
             break;
 
         case EAST:
-            im->xOriginTitle   = Xvertical + Xylabel + im->xsize / 2;
+            im->xOriginTitle   = im->xsize / 2;
             im->yOriginTitle   = 0;
 
             im->xOriginLegend  = Xvertical + Xylabel + Xmain + Xvertical2;
@@ -3389,6 +3410,12 @@ int graph_paint(
         cairo_svg_surface_restrict_to_version
             (im->surface, CAIRO_SVG_VERSION_1_1);
         break;
+    case IF_XML:
+    case IF_CSV:
+    case IF_TSV:
+    case IF_SSV:
+    case IF_JSON:
+        break;
     };
     cairo_destroy(im->cr);
     im->cr = cairo_create(im->surface);
@@ -4001,6 +4028,10 @@ int rrd_graph(
 ** - options parsing  now in rrd_graph_options()
 ** - script parsing   now in rrd_graph_script()
 */
+
+/* have no better idea where to put it - rrd.h does not work */
+int       rrd_graph_xport(image_desc_t *);
+
 rrd_info_t *rrd_graph_v(
     int argc,
     char **argv)
@@ -4052,6 +4083,10 @@ rrd_info_t *rrd_graph_v(
         return NULL;
     }
 
+    if (im.imgformat >= IF_XML) {
+      rrd_graph_xport(&im);
+   } else {
+
     /* Everything is now read and the actual work can start */
 
     if (graph_paint(&im) == -1) {
@@ -4059,7 +4094,7 @@ rrd_info_t *rrd_graph_v(
         im_free(&im);
         return NULL;
     }
-
+   }
 
     /* The image is generated and needs to be output.
      ** Also, if needed, print a line with information about the image.
@@ -4152,6 +4187,7 @@ void rrd_graph_init(
     im->maxval = DNAN;
     im->minval = 0;
     im->minval = DNAN;
+    im->magfact = 1;
     im->prt_c = 0;
     im->rigid = 0;
     im->rendered_image_size = 0;
@@ -4301,6 +4337,7 @@ void rrd_graph_options(
         { "border",             required_argument, 0, 1007},
         { "grid-dash",          required_argument, 0, 1008},
         { "dynamic-labels",     no_argument,       0, 1009},
+        { "week-fmt",           required_argument, 0, 1010},
         {  0, 0, 0, 0}
 };
 /* *INDENT-ON* */
@@ -4486,6 +4523,10 @@ void rrd_graph_options(
         case 1009: /* enable dynamic labels */
             im->dynamic_labels = 1;
             break;         
+        case 1010:
+            strncpy(week_fmt,optarg,sizeof week_fmt);
+            week_fmt[(sizeof week_fmt)-1]='\0';
+            break;
         case 1002: /* right y axis */
 
             if(sscanf(optarg,