Merge branch 'collectd-5.6'
[collectd.git] / src / rrdcached.c
index 3db89b5..6d45ac9 100644 (file)
@@ -287,10 +287,31 @@ static int rc_config (oconfig_item_t *ci)
   return (0);
 } /* int rc_config */
 
+static int try_reconnect (void)
+{
+  int status;
+
+  rrdc_disconnect ();
+
+  rrd_clear_error ();
+  status = rrdc_connect (daemon_address);
+  if (status != 0)
+  {
+    ERROR ("rrdcached plugin: Failed to reconnect to RRDCacheD "
+        "at %s: %s (status=%d)", daemon_address, rrd_get_error (), status);
+    return (-1);
+  }
+
+  INFO ("rrdcached plugin: Successfully reconnected to RRDCacheD "
+      "at %s", daemon_address);
+  return (0);
+} /* int try_reconnect */
+
 static int rc_read (void)
 {
   int status;
   rrdc_stats_t *head;
+  _Bool retried = 0;
 
   value_list_t vl = VALUE_LIST_INIT;
   vl.values = &(value_t) { .gauge = NAN };
@@ -307,19 +328,35 @@ static int rc_read (void)
     sstrncpy (vl.host, daemon_address, sizeof (vl.host));
   sstrncpy (vl.plugin, "rrdcached", sizeof (vl.plugin));
 
+  rrd_clear_error ();
   status = rrdc_connect (daemon_address);
   if (status != 0)
   {
-    ERROR ("rrdcached plugin: rrdc_connect (%s) failed with status %i.",
-        daemon_address, status);
+    ERROR ("rrdcached plugin: Failed to connect to RRDCacheD "
+        "at %s: %s (status=%d)", daemon_address, rrd_get_error (), status);
     return (-1);
   }
 
-  head = NULL;
-  status = rrdc_stats_get (&head);
-  if (status != 0)
+  while (42)
   {
-    ERROR ("rrdcached plugin: rrdc_stats_get failed with status %i.", status);
+    /* The RRD client lib does not provide any means for checking a
+     * connection, hence we'll have to retry upon failed operations. */
+    head = NULL;
+    rrd_clear_error ();
+    status = rrdc_stats_get (&head);
+    if (status == 0)
+      break;
+
+    if (!retried)
+    {
+      retried = 1;
+      if (try_reconnect () == 0)
+        continue;
+      /* else: report the error and fail */
+    }
+
+    ERROR ("rrdcached plugin: rrdc_stats_get failed: %s (status=%i).",
+        rrd_get_error (), status);
     return (-1);
   }
 
@@ -407,6 +444,7 @@ static int rc_write (const data_set_t *ds, const value_list_t *vl,
   char values[512];
   char *values_array[2];
   int status;
+  _Bool retried = 0;
 
   if (daemon_address == NULL)
   {
@@ -463,20 +501,34 @@ static int rc_write (const data_set_t *ds, const value_list_t *vl,
     }
   }
 
+  rrd_clear_error ();
   status = rrdc_connect (daemon_address);
   if (status != 0)
   {
-    ERROR ("rrdcached plugin: rrdc_connect (%s) failed with status %i.",
-        daemon_address, status);
+    ERROR ("rrdcached plugin: Failed to connect to RRDCacheD "
+        "at %s: %s (status=%d)", daemon_address, rrd_get_error (), status);
     return (-1);
   }
 
-  status = rrdc_update (filename, /* values_num = */ 1, (void *) values_array);
-  if (status != 0)
+  while (42)
   {
-    ERROR ("rrdcached plugin: rrdc_update (%s, [%s], 1) failed with "
-        "status %i.",
-        filename, values_array[0], status);
+    /* The RRD client lib does not provide any means for checking a
+     * connection, hence we'll have to retry upon failed operations. */
+    rrd_clear_error ();
+    status = rrdc_update (filename, /* values_num = */ 1, (void *) values_array);
+    if (status == 0)
+      break;
+
+    if (!retried)
+    {
+      retried = 1;
+      if (try_reconnect () == 0)
+        continue;
+      /* else: report the error and fail */
+    }
+
+    ERROR ("rrdcached plugin: rrdc_update (%s, [%s], 1) failed: %s (status=%i)",
+        filename, values_array[0], rrd_get_error (), status);
     return (-1);
   }
 
@@ -489,6 +541,7 @@ static int rc_flush (__attribute__((unused)) cdtime_t timeout, /* {{{ */
 {
   char filename[PATH_MAX + 1];
   int status;
+  _Bool retried = 0;
 
   if (identifier == NULL)
     return (EINVAL);
@@ -498,19 +551,34 @@ static int rc_flush (__attribute__((unused)) cdtime_t timeout, /* {{{ */
   else
     ssnprintf (filename, sizeof (filename), "%s.rrd", identifier);
 
+  rrd_clear_error ();
   status = rrdc_connect (daemon_address);
   if (status != 0)
   {
-    ERROR ("rrdcached plugin: rrdc_connect (%s) failed with status %i.",
-        daemon_address, status);
+    ERROR ("rrdcached plugin: Failed to connect to RRDCacheD "
+        "at %s: %s (status=%d)", daemon_address, rrd_get_error (), status);
     return (-1);
   }
 
-  status = rrdc_flush (filename);
-  if (status != 0)
+  while (42)
   {
-    ERROR ("rrdcached plugin: rrdc_flush (%s) failed with status %i.",
-        filename, status);
+    /* The RRD client lib does not provide any means for checking a
+     * connection, hence we'll have to retry upon failed operations. */
+    rrd_clear_error ();
+    status = rrdc_flush (filename);
+    if (status == 0)
+      break;
+
+    if (!retried)
+    {
+      retried = 1;
+      if (try_reconnect () == 0)
+        continue;
+      /* else: report the error and fail */
+    }
+
+    ERROR ("rrdcached plugin: rrdc_flush (%s) failed: %s (status=%i).",
+        filename, rrd_get_error (), status);
     return (-1);
   }
   DEBUG ("rrdcached plugin: rrdc_flush (%s): Success.", filename);