Merge branch 'master' into collectd-4
[collectd.git] / src / rrdtool.c
index ec04642..b221341 100644 (file)
 #include "common.h"
 #include "utils_avltree.h"
 
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+
 /*
  * Private types
  */
@@ -78,6 +82,7 @@ static int         cache_timeout = 0;
 static int         cache_flush_timeout = 0;
 static time_t      cache_flush_last;
 static avl_tree_t *cache = NULL;
+static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
 
 /* * * * * * * * * *
  * WARNING:  Magic *
@@ -181,8 +186,9 @@ static int ds_get (char ***ret, const data_set_t *ds)
        ds_def = (char **) malloc (ds->ds_num * sizeof (char *));
        if (ds_def == NULL)
        {
+               char errbuf[1024];
                ERROR ("rrdtool plugin: malloc failed: %s",
-                               strerror (errno));
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
                return (-1);
        }
        memset (ds_def, '\0', ds->ds_num * sizeof (char *));
@@ -286,7 +292,9 @@ static int rrd_create_file (char *filename, const data_set_t *ds)
 
        if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
        {
-               ERROR ("rrd_create failed: %s", strerror (errno));
+               char errbuf[1024];
+               ERROR ("rrd_create failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
                return (-1);
        }
 
@@ -428,8 +436,9 @@ static rrd_cache_t *rrd_cache_insert (const char *filename,
                        (rc->values_num + 1) * sizeof (char *));
        if (rc->values == NULL)
        {
+               char errbuf[1024];
                ERROR ("rrdtool plugin: realloc failed: %s",
-                               strerror (errno));
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
                if (cache != NULL)
                {
                        void *cache_key = NULL;
@@ -454,8 +463,9 @@ static rrd_cache_t *rrd_cache_insert (const char *filename,
 
                if (cache_key == NULL)
                {
+                       char errbuf[1024];
                        ERROR ("rrdtool plugin: strdup failed: %s",
-                                       strerror (errno));
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
                        sfree (rc->values[0]);
                        sfree (rc->values);
                        sfree (rc);
@@ -480,6 +490,9 @@ static int rrd_write_cache_entry (const char *filename, rrd_cache_t *rc)
 
        int i;
 
+       if (rc->values_num < 1)
+               return (0);
+
        argc = rc->values_num + 2;
        argv = (char **) malloc ((argc + 1) * sizeof (char *));
        if (argv == NULL)
@@ -502,10 +515,15 @@ static int rrd_write_cache_entry (const char *filename, rrd_cache_t *rc)
        optind = 0; /* bug in librrd? */
        rrd_clear_error ();
        status = rrd_update (argc, argv);
+       if (status != 0)
+       {
+               WARNING ("rrd_update failed: %s: %s",
+                               filename, rrd_get_error ());
+               status = -1;
+       }
 
        free (argv);
        free (fn);
-
        /* Free the value list of `rc' */
        for (i = 0; i < rc->values_num; i++)
                free (rc->values[i]);
@@ -513,14 +531,7 @@ static int rrd_write_cache_entry (const char *filename, rrd_cache_t *rc)
        rc->values = NULL;
        rc->values_num = 0;
 
-       if (status != 0)
-       {
-               WARNING ("rrd_update failed: %s: %s",
-                               filename, rrd_get_error ());
-               return (-1);
-       }
-
-       return (0);
+       return (status);
 } /* int rrd_write_cache_entry */
 
 static void rrd_cache_flush (int timeout)
@@ -553,10 +564,11 @@ static void rrd_cache_flush (int timeout)
                                        (keys_num + 1) * sizeof (char *));
                        if (keys == NULL)
                        {
-                               DEBUG ("realloc failed: %s", strerror (errno));
+                               char errbuf[1024];
                                ERROR ("rrdtool plugin: "
                                                "realloc failed: %s",
-                                               strerror (errno));
+                                               sstrerror (errno, errbuf,
+                                                       sizeof (errbuf)));
                                avl_iterator_destroy (iter);
                                return;
                        }
@@ -610,8 +622,10 @@ static int rrd_write (const data_set_t *ds, const value_list_t *vl)
                }
                else
                {
-                       ERROR ("stat(%s) failed: %s",
-                                       filename, strerror (errno));
+                       char errbuf[1024];
+                       ERROR ("stat(%s) failed: %s", filename,
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
                        return (-1);
                }
        }
@@ -622,15 +636,20 @@ static int rrd_write (const data_set_t *ds, const value_list_t *vl)
                return (-1);
        }
 
+       pthread_mutex_lock (&cache_lock);
        rc = rrd_cache_insert (filename, values);
        if (rc == NULL)
+       {
+               pthread_mutex_unlock (&cache_lock);
                return (-1);
+       }
 
        if (cache == NULL)
        {
                rrd_write_cache_entry (filename, rc);
                /* rc's value-list is free's by `rrd_write_cache_entry' */
                sfree (rc);
+               pthread_mutex_unlock (&cache_lock);
                return (0);
        }
 
@@ -646,6 +665,7 @@ static int rrd_write (const data_set_t *ds, const value_list_t *vl)
        if ((now - cache_flush_last) >= cache_flush_timeout)
                rrd_cache_flush (cache_flush_timeout);
 
+       pthread_mutex_unlock (&cache_lock);
        return (0);
 } /* int rrd_write */
 
@@ -746,10 +766,12 @@ static int rrd_config (const char *key, const char *value)
 
 static int rrd_shutdown (void)
 {
+       pthread_mutex_lock (&cache_lock);
        rrd_cache_flush (-1);
        if (cache != NULL)
                avl_destroy (cache);
        cache = NULL;
+       pthread_mutex_unlock (&cache_lock);
 
        return (0);
 } /* int rrd_shutdown */
@@ -770,6 +792,7 @@ static int rrd_init (void)
                                "smaller than your `interval'. This will "
                                "create needlessly big RRD-files.");
 
+       pthread_mutex_lock (&cache_lock);
        if (cache_timeout < 2)
        {
                cache_timeout = 0;
@@ -784,15 +807,17 @@ static int rrd_init (void)
                cache_flush_last = time (NULL);
                plugin_register_shutdown ("rrdtool", rrd_shutdown);
        }
+       pthread_mutex_unlock (&cache_lock);
 
-       DEBUG ("datadir = %s; stepsize = %i; heartbeat = %i; rrarows = %i; xff = %lf;",
+       DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %i;"
+                       " heartbeat = %i; rrarows = %i; xff = %lf;",
                        (datadir == NULL) ? "(null)" : datadir,
                        stepsize, heartbeat, rrarows, xff);
 
        return (0);
 } /* int rrd_init */
 
-void module_register (void)
+void module_register (modreg_e load)
 {
        plugin_register_config ("rrdtool", rrd_config,
                        config_keys, config_keys_num);