"instance_data_json" action: Implement the "resolution" parameter.
[collection4.git] / src / graph_ident.c
index 3635990..abf396d 100644 (file)
@@ -21,6 +21,8 @@
  *   Florian octo Forster <ff at octo.it>
  **/
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -30,6 +32,8 @@
 #include <limits.h> /* PATH_MAX */
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <math.h>
+#include <assert.h>
 
 #include "graph_ident.h"
 #include "common.h"
@@ -542,6 +546,7 @@ struct ident_data_to_json__data_s
 {
   dp_time_t begin;
   dp_time_t end;
+  dp_time_t interval;
   yajl_gen handler;
 };
 typedef struct ident_data_to_json__data_s ident_data_to_json__data_t;
@@ -552,27 +557,81 @@ typedef struct ident_data_to_json__data_s ident_data_to_json__data_t;
 static int ident_data_to_json__get_ident_data (
     __attribute__((unused)) graph_ident_t *ident, /* {{{ */
     __attribute__((unused)) const char *ds_name,
-    const dp_data_point_t *dp, size_t dp_num,
+    dp_time_t first_value_time, dp_time_t interval,
+    size_t data_points_num, double *data_points,
     void *user_data)
 {
   ident_data_to_json__data_t *data = user_data;
   size_t i;
 
+  double first_value_time_double;
+  double interval_double;
+  double interval_requested;
+  size_t points_consolidate;
+
+  first_value_time_double = ((double) first_value_time.tv_sec)
+    + (((double) first_value_time.tv_nsec) / 1000000000.0);
+  interval_double = ((double) interval.tv_sec)
+    + (((double) interval.tv_nsec) / 1000000000.0);
+  interval_requested = ((double) data->interval.tv_sec)
+    + (((double) data->interval.tv_nsec) / 1000000000.0);
+
+  if (interval_requested < (2.0 * interval_double))
+    points_consolidate = 1;
+  else
+    points_consolidate = (size_t) (interval_requested / interval_double);
+  assert (points_consolidate >= 1);
+
+  if (points_consolidate > 1)
+  {
+    size_t offset = data_points_num % points_consolidate;
+
+    first_value_time_double += ((double) offset) * interval_double;
+    interval_double *= ((double) points_consolidate);
+  }
+
   yajl_gen_map_open (data->handler);
 
-  for (i = 0; i < dp_num; i++)
+  yajl_gen_string_cast (data->handler, "first_value_time", strlen ("first_value_time"));
+  yajl_gen_double (data->handler, first_value_time_double);
+
+  yajl_gen_string_cast (data->handler, "interval", strlen ("interval"));
+  yajl_gen_double (data->handler, interval_double);
+
+  yajl_gen_string_cast (data->handler, "data", strlen ("data"));
+  yajl_gen_array_open (data->handler);
+
+  for (i = (data_points_num % points_consolidate);
+      i < data_points_num;
+      i += points_consolidate)
   {
-    yajl_gen_map_open (data->handler);
-    yajl_gen_integer (data->handler, (long) dp[i].time.tv_sec);
-    yajl_gen_double (data->handler, dp[i].value);
-    yajl_gen_map_close (data->handler);
+    size_t j;
+
+    double sum = 0.0;
+    long num = 0;
+
+    for (j = 0; j < points_consolidate; j++)
+    {
+      if (isnan (data_points[i+j]))
+        continue;
+
+      sum += data_points[i+j];
+      num++;
+    }
+
+    if (num == 0)
+      yajl_gen_null (data->handler);
+    else
+      yajl_gen_double (data->handler, sum / ((double) num));
   }
 
-  yajl_gen_map_close (data->handler);
+  yajl_gen_array_close (data->handler);
+
+  return (0);
 } /* }}} int ident_data_to_json__get_ident_data */
 
 /* Called for each DS name */
-static int ident_data_to_json__get_ds_name (const graph_ident_t *ident, /* {{{ */
+static int ident_data_to_json__get_ds_name (graph_ident_t *ident, /* {{{ */
     const char *ds_name, void *user_data)
 {
   ident_data_to_json__data_t *data = user_data;
@@ -580,36 +639,42 @@ static int ident_data_to_json__get_ds_name (const graph_ident_t *ident, /* {{{ *
 
   yajl_gen_map_open (data->handler);
 
-  yajl_gen_string_cast (data->handler, "ds_name", strlen ("ds_name"));
-  yajl_gen_string_cast (data->handler, ds_name, strlen (ds_name));
+  yajl_gen_string_cast (data->handler, "file", strlen ("file"));
+  ident_to_json (ident, data->handler);
 
-  yajl_gen_string_cast (data->handler, "data", strlen ("data"));
-  yajl_gen_array_open (data->handler);
+  yajl_gen_string_cast (data->handler, "data_source", strlen ("data_source"));
+  yajl_gen_string_cast (data->handler, ds_name, strlen (ds_name));
 
   status = data_provider_get_ident_data (ident, ds_name,
       data->begin, data->end,
       ident_data_to_json__get_ident_data,
       data);
 
-  yajl_gen_array_close (data->handler);
   yajl_gen_map_close (data->handler);
 
   return (status);
 } /* }}} int ident_data_to_json__get_ds_name */
 
-int ident_data_to_json (const graph_ident_t *ident, /* {{{ */
-    dp_time_t begin, dp_time_t end,
+int ident_data_to_json (graph_ident_t *ident, /* {{{ */
+    dp_time_t begin, dp_time_t end, dp_time_t res,
     yajl_gen handler)
 {
   ident_data_to_json__data_t data;
+  int status;
 
   data.begin = begin;
   data.end = end;
+  data.interval = res;
   data.handler = handler;
 
   /* Iterate over all DS names */
-  return (data_provider_get_ident_ds_names (ident,
-        ident_data_to_json__get_ds_name, &data));
+  status = data_provider_get_ident_ds_names (ident,
+      ident_data_to_json__get_ds_name, &data);
+  if (status != 0)
+    fprintf (stderr, "ident_data_to_json: data_provider_get_ident_ds_names "
+        "failed with status %i\n", status);
+
+  return (status);
 } /* }}} int ident_data_to_json */
 /* }}} ident_data_to_json */