Merge branch 'master' into ff/rrdd
[rrdtool.git] / src / rrd_update.c
index 8eab0e9..5536c3c 100644 (file)
@@ -1,6 +1,7 @@
 
 /*****************************************************************************
- * RRDtool 1.2.99907080300  Copyright by Tobi Oetiker, 1997-2007
+ * RRDtool 1.3.0  Copyright by Tobi Oetiker, 1997-2008
+ *                Copyright by Florian Forster, 2008
  *****************************************************************************
  * rrd_update.c  RRD Update Function
  *****************************************************************************
@@ -23,6 +24,8 @@
 #include "rrd_is_thread_safe.h"
 #include "unused.h"
 
+#include "rrd_client.h"
+
 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
 /*
  * WIN32 does not have gettimeofday    and struct timeval. This is a quick and dirty
@@ -71,7 +74,7 @@ int       _rrd_update(
     const char *tmplt,
     int argc,
     const char **argv,
-    info_t *);
+    rrd_info_t *);
 
 static int allocate_data_structures(
     rrd_t *rrd,
@@ -104,7 +107,7 @@ static int process_arg(
     char **updvals,
     long *tmpl_idx,
     unsigned long tmpl_cnt,
-    info_t **pcdp_summary,
+    rrd_info_t ** pcdp_summary,
     int version,
     unsigned long *skip_update,
     int *schedule_smooth);
@@ -258,7 +261,7 @@ static int write_to_rras(
     unsigned long *rra_current,
     time_t current_time,
     unsigned long *skip_update,
-    info_t **pcdp_summary);
+    rrd_info_t ** pcdp_summary);
 
 static int write_RRA_row(
     rrd_file_t *rrd_file,
@@ -266,7 +269,7 @@ static int write_RRA_row(
     unsigned long rra_idx,
     unsigned long *rra_current,
     unsigned short CDP_scratch_idx,
-    info_t **pcdp_summary,
+    rrd_info_t ** pcdp_summary,
     time_t rra_time);
 
 static int smooth_all_rras(
@@ -317,13 +320,13 @@ static inline void initialize_time(
 
 #define IFDNAN(X,Y) (isnan(X) ? (Y) : (X));
 
-info_t   *rrd_update_v(
+rrd_info_t *rrd_update_v(
     int argc,
     char **argv)
 {
     char     *tmplt = NULL;
-    info_t   *result = NULL;
-    infoval   rc;
+    rrd_info_t *result = NULL;
+    rrd_infoval_t rc;
     struct option long_options[] = {
         {"template", required_argument, 0, 't'},
         {0, 0, 0, 0}
@@ -359,7 +362,7 @@ info_t   *rrd_update_v(
         goto end_tag;
     }
     rc.u_int = 0;
-    result = info_push(NULL, sprintf_alloc("return_value"), RD_I_INT, rc);
+    result = rrd_info_push(NULL, sprintf_alloc("return_value"), RD_I_INT, rc);
     rc.u_int = _rrd_update(argv[optind], tmplt,
                            argc - optind - 1,
                            (const char **) (argv + optind + 1), result);
@@ -374,18 +377,20 @@ int rrd_update(
 {
     struct option long_options[] = {
         {"template", required_argument, 0, 't'},
+        {"daemon",   required_argument, 0, 'd'},
         {0, 0, 0, 0}
     };
     int       option_index = 0;
     int       opt;
     char     *tmplt = NULL;
     int       rc = -1;
+    char     *daemon = NULL;
 
     optind = 0;
     opterr = 0;         /* initialize getopt */
 
     while (1) {
-        opt = getopt_long(argc, argv, "t:", long_options, &option_index);
+        opt = getopt_long(argc, argv, "t:d:", long_options, &option_index);
 
         if (opt == EOF)
             break;
@@ -395,6 +400,17 @@ int rrd_update(
             tmplt = strdup(optarg);
             break;
 
+        case 'd':
+            if (daemon != NULL)
+                free (daemon);
+            daemon = strdup (optarg);
+            if (daemon == NULL)
+            {
+                rrd_set_error("strdup failed.");
+                goto out;
+            }
+            break;
+
         case '?':
             rrd_set_error("unknown option '%s'", argv[optind - 1]);
             goto out;
@@ -407,10 +423,71 @@ int rrd_update(
         goto out;
     }
 
+    if ((tmplt != NULL) && (daemon != NULL))
+    {
+        rrd_set_error("The caching daemon cannot be used together with "
+                "templates yet.");
+        goto out;
+    }
+
+    if ((tmplt == NULL) && (daemon == NULL))
+    {
+        char *temp;
+
+        temp = getenv (ENV_RRDCACHED_ADDRESS);
+        if (temp != NULL)
+        {
+            daemon = strdup (temp);
+            if (daemon == NULL)
+            {
+                rrd_set_error("strdup failed.");
+                goto out;
+            }
+        }
+    }
+
+    if (daemon != NULL)
+    {
+        int status;
+
+        status = rrdc_connect (daemon);
+        if (status != 0)
+        {
+            rrd_set_error("Unable to connect to daemon: %s",
+                    (status < 0)
+                    ? "Internal error"
+                    : rrd_strerror (status));
+            goto out;
+        }
+
+        status = rrdc_update (/* file = */ argv[optind],
+                /* values_num = */ argc - optind - 1,
+                /* values = */ (void *) (argv + optind + 1));
+        if (status != 0)
+        {
+            rrd_set_error("Failed sending the values to the daemon: %s",
+                    (status < 0)
+                    ? "Internal error"
+                    : rrd_strerror (status));
+        }
+
+        rrdc_disconnect ();
+        goto out;
+    } /* if (daemon != NULL) */
+
     rc = rrd_update_r(argv[optind], tmplt,
                       argc - optind - 1, (const char **) (argv + optind + 1));
   out:
-    free(tmplt);
+    if (tmplt != NULL)
+    {
+        free(tmplt);
+        tmplt = NULL;
+    }
+    if (daemon != NULL)
+    {
+        free (daemon);
+        daemon = NULL;
+    }
     return rc;
 }
 
@@ -428,7 +505,7 @@ int _rrd_update(
     const char *tmplt,
     int argc,
     const char **argv,
-    info_t *pcdp_summary)
+    rrd_info_t * pcdp_summary)
 {
 
     int       arg_i = 2;
@@ -479,7 +556,7 @@ int _rrd_update(
     /* get exclusive lock to whole file.
      * lock gets removed when we close the file.
      */
-    if (LockRRD(rrd_file->fd) != 0) {
+    if (rrd_lock(rrd_file) != 0) {
         rrd_set_error("could not lock RRD");
         goto err_close;
     }
@@ -502,6 +579,15 @@ int _rrd_update(
                         rra_step_cnt, updvals, tmpl_idx, tmpl_cnt,
                         &pcdp_summary, version, skip_update,
                         &schedule_smooth) == -1) {
+           if (rrd_test_error()) { /* Should have error string always here */
+               char *save_error;
+
+               /* Prepend file name to error message */
+               if ((save_error = strdup(rrd_get_error())) != NULL) {
+                   rrd_set_error("%s: %s", filename, save_error);
+                   free(save_error);
+               }
+           }
             free(arg_copy);
             break;
         }
@@ -560,8 +646,8 @@ int _rrd_update(
  *
  * returns 0 on success
  */
-int LockRRD(
-    int in_file)
+int rrd_lock(
+    rrd_file_t *file)
 {
     int       rcstat;
 
@@ -569,8 +655,8 @@ int LockRRD(
 #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
         struct _stat st;
 
-        if (_fstat(in_file, &st) == 0) {
-            rcstat = _locking(in_file, _LK_NBLCK, st.st_size);
+        if (_fstat(file->fd, &st) == 0) {
+            rcstat = _locking(file->fd, _LK_NBLCK, st.st_size);
         } else {
             rcstat = -1;
         }
@@ -582,7 +668,7 @@ int LockRRD(
         lock.l_start = 0;   /* start of file */
         lock.l_whence = SEEK_SET;   /* end of file */
 
-        rcstat = fcntl(in_file, F_SETLK, &lock);
+        rcstat = fcntl(file->fd, F_SETLK, &lock);
 #endif
     }
 
@@ -750,7 +836,7 @@ static int process_arg(
     char **updvals,
     long *tmpl_idx,
     unsigned long tmpl_cnt,
-    info_t **pcdp_summary,
+    rrd_info_t ** pcdp_summary,
     int version,
     unsigned long *skip_update,
     int *schedule_smooth)
@@ -832,6 +918,9 @@ static int process_arg(
     rrd->live_head->last_up = *current_time;
     rrd->live_head->last_up_usec = *current_time_usec;
 
+    if (version < 3) {
+        *rrd->legacy_last_up = rrd->live_head->last_up;
+    }
     free(seasonal_coef);
     free(last_seasonal_coef);
     return 0;
@@ -923,12 +1012,12 @@ static int get_time_from_reading(
     double    tmp;
     char     *parsetime_error = NULL;
     char     *old_locale;
-    struct rrd_time_value ds_tv;
+    rrd_time_value_t ds_tv;
     struct timeval tmp_time;    /* used for time conversion */
 
     /* get the time from the reading ... handle N */
     if (timesyntax == '@') {    /* at-style */
-        if ((parsetime_error = parsetime(updvals[0], &ds_tv))) {
+        if ((parsetime_error = rrd_parsetime(updvals[0], &ds_tv))) {
             rrd_set_error("ds time: %s: %s", updvals[0], parsetime_error);
             return -1;
         }
@@ -1852,7 +1941,7 @@ static int write_to_rras(
     unsigned long *rra_current,
     time_t current_time,
     unsigned long *skip_update,
-    info_t **pcdp_summary)
+    rrd_info_t ** pcdp_summary)
 {
     unsigned long rra_idx;
     unsigned long rra_start;
@@ -1960,11 +2049,11 @@ static int write_RRA_row(
     unsigned long rra_idx,
     unsigned long *rra_current,
     unsigned short CDP_scratch_idx,
-    info_t **pcdp_summary,
+    rrd_info_t ** pcdp_summary,
     time_t rra_time)
 {
     unsigned long ds_idx, cdp_idx;
-    infoval   iv;
+    rrd_infoval_t iv;
 
     for (ds_idx = 0; ds_idx < rrd->stat_head->ds_cnt; ds_idx++) {
         /* compute the cdp index */
@@ -1977,15 +2066,13 @@ static int write_RRA_row(
         if (*pcdp_summary != NULL) {
             iv.u_val = rrd->cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val;
             /* append info to the return hash */
-            *pcdp_summary = info_push(*pcdp_summary,
-                                      sprintf_alloc("[%d]RRA[%s][%lu]DS[%s]",
-                                                    rra_time,
-                                                    rrd->rra_def[rra_idx].
-                                                    cf_nam,
-                                                    rrd->rra_def[rra_idx].
-                                                    pdp_cnt,
-                                                    rrd->ds_def[ds_idx].
-                                                    ds_nam), RD_I_VAL, iv);
+            *pcdp_summary = rrd_info_push(*pcdp_summary,
+                                          sprintf_alloc
+                                          ("[%d]RRA[%s][%lu]DS[%s]", rra_time,
+                                           rrd->rra_def[rra_idx].cf_nam,
+                                           rrd->rra_def[rra_idx].pdp_cnt,
+                                           rrd->ds_def[ds_idx].ds_nam),
+                                          RD_I_VAL, iv);
         }
         if (rrd_write(rrd_file,
                       &(rrd->cdp_prep[cdp_idx].scratch[CDP_scratch_idx].
@@ -2053,7 +2140,7 @@ static int write_changes_to_disk(
             return -1;
         }
     } else {
-        if (rrd_write(rrd_file, &rrd->live_head->last_up,
+        if (rrd_write(rrd_file, rrd->legacy_last_up,
                       sizeof(time_t) * 1) != sizeof(time_t) * 1) {
             rrd_set_error("rrd_write live_head to rrd");
             return -1;