locally, or B<DataDir> is set to a relative path, this will not work as
expected. Default is B<true>.
+=item B<CreateFilesAsync> B<false>|B<true>
+
+When enabled, new RRD files are enabled asynchronously, using a separate thread
+that runs in the background. This prevents writes to block, which is a problem
+especially when many hundreds of files need to be created at once. However,
+this may lead to transient errors reported by code that assumes that the files
+are already existing. When disabled (the default) files are created
+synchronously, blocking for a short while, while the file is being written.
+
=item B<StepSize> I<Seconds>
B<Force> the stepsize of newly created RRD-files. Ideally (and per default)
=item B<DataDir> I<Directory>
-Set the directory to store RRD-files under. Per default RRD-files are generated
-beneath the daemon's working directory, i.E<nbsp>e. the B<BaseDir>.
+Set the directory to store RRD files under. By default RRD files are generated
+beneath the daemon's working directory, i.e. the B<BaseDir>.
+
+=item B<CreateFilesAsync> B<false>|B<true>
+
+When enabled, new RRD files are enabled asynchronously, using a separate thread
+that runs in the background. This prevents writes to block, which is a problem
+especially when many hundreds of files need to be created at once. However,
+this may lead to transient errors reported by code that assumes that the files
+are already existing. When disabled (the default) files are created
+synchronously, blocking for a short while, while the file is being written.
=item B<StepSize> I<Seconds>
The C<rrdtool plugin> calculates the number of PDPs per CDP based on the
B<StepSize>, this setting and a timespan. This plugin creates RRD-files with
-three times five RRAs, i. e. five RRAs with the CFs B<MIN>, B<AVERAGE>, and
+three times five RRAs, i.e. five RRAs with the CFs B<MIN>, B<AVERAGE>, and
B<MAX>. The five RRAs are optimized for graphs covering one hour, one day, one
week, one month, and one year.
/**
* collectd - src/utils_rrdcreate.c
- * Copyright (C) 2006-2008 Florian octo Forster
+ * Copyright (C) 2006-2013 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
**/
#include "collectd.h"
#include <pthread.h>
#include <rrd.h>
+struct srrd_create_args_s
+{
+ char *filename;
+ unsigned long pdp_step;
+ time_t last_up;
+ int argc;
+ char **argv;
+};
+typedef struct srrd_create_args_s srrd_create_args_t;
+
/*
* Private variables
*/
sfree (rra_def);
} /* }}} void rra_free */
+static void srrd_create_args_destroy (srrd_create_args_t *args)
+{
+ if (args == NULL)
+ return;
+
+ sfree (args->filename);
+ if (args->argv != NULL)
+ {
+ int i;
+ for (i = 0; i < args->argc; i++)
+ sfree (args->argv[i]);
+ sfree (args->argv);
+ }
+} /* void srrd_create_args_destroy */
+
+static srrd_create_args_t *srrd_create_args_create (const char *filename,
+ unsigned long pdp_step, time_t last_up,
+ int argc, const char **argv)
+{
+ srrd_create_args_t *args;
+
+ args = malloc (sizeof (*args));
+ if (args == NULL)
+ {
+ ERROR ("srrd_create_args_create: malloc failed.");
+ return (NULL);
+ }
+ memset (args, 0, sizeof (*args));
+ args->filename = NULL;
+ args->pdp_step = pdp_step;
+ args->last_up = last_up;
+ args->argv = NULL;
+
+ args->filename = strdup (filename);
+ if (args->filename == NULL)
+ {
+ ERROR ("srrd_create_args_create: strdup failed.");
+ srrd_create_args_destroy (args);
+ return (NULL);
+ }
+
+ args->argv = calloc ((size_t) (argc + 1), sizeof (*args->argv));
+ if (args->argv == NULL)
+ {
+ ERROR ("srrd_create_args_create: calloc failed.");
+ srrd_create_args_destroy (args);
+ return (NULL);
+ }
+
+ for (args->argc = 0; args->argc < argc; args->argc++)
+ {
+ args->argv[args->argc] = strdup (argv[args->argc]);
+ if (args->argv[args->argc] == NULL)
+ {
+ ERROR ("srrd_create_args_create: strdup failed.");
+ srrd_create_args_destroy (args);
+ return (NULL);
+ }
+ }
+ assert (args->argc == argc);
+ args->argv[args->argc] = NULL;
+
+ return (args);
+} /* srrd_create_args_t *srrd_create_args_create */
+
/* * * * * * * * * *
* WARNING: Magic *
* * * * * * * * * */
} /* }}} int srrd_create */
#endif /* !HAVE_THREADSAFE_LIBRRD */
+static void *srrd_create_thread (void *targs)
+{
+ srrd_create_args_t *args = targs;
+ int status;
+
+ status = srrd_create (args->filename, args->pdp_step, args->last_up,
+ args->argc, (void *) args->argv);
+ if (status != 0)
+ {
+ WARNING ("srrd_create_thread: srrd_create (%s) returned status %i.",
+ args->filename, status);
+ }
+ else
+ {
+ DEBUG ("srrd_create_thread: Successfully created RRD file \"%s\".",
+ args->filename);
+ }
+
+ srrd_create_args_destroy (args);
+
+ return (0);
+} /* void *srrd_create_thread */
+
+static int srrd_create_async (const char *filename,
+ unsigned long pdp_step, time_t last_up,
+ int argc, const char **argv)
+{
+ srrd_create_args_t *args;
+ pthread_t thread;
+ pthread_attr_t attr;
+ int status;
+
+ args = srrd_create_args_create (filename, pdp_step, last_up, argc, argv);
+ if (args == NULL)
+ return (-1);
+
+ status = pthread_attr_init (&attr);
+ if (status != 0)
+ return (-1);
+
+ status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ if (status != 0)
+ return (-1);
+
+ status = pthread_create (&thread, &attr, srrd_create_thread, args);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ ERROR ("srrd_create_async: pthread_create failed: %s",
+ sstrerror (status, errbuf, sizeof (errbuf)));
+ pthread_attr_destroy (&attr);
+ srrd_create_args_destroy (args);
+ return (status);
+ }
+
+ pthread_attr_destroy (&attr);
+ return (0);
+}
+
/*
* Public functions
*/
else
stepsize = (unsigned long) CDTIME_T_TO_TIME_T (vl->interval);
- status = srrd_create (filename, stepsize, last_up,
- argc, (const char **) argv);
-
- free (argv);
- ds_free (ds_num, ds_def);
- rra_free (rra_num, rra_def);
-
- if (status != 0)
+ if (cfg->async)
{
- WARNING ("cu_rrd_create_file: srrd_create (%s) returned status %i.",
- filename, status);
+ status = srrd_create_async (filename, stepsize, last_up,
+ argc, (const char **) argv);
+ if (status != 0)
+ WARNING ("cu_rrd_create_file: srrd_create_async (%s) "
+ "returned status %i.",
+ filename, status);
}
- else
+ else /* synchronous */
{
- DEBUG ("cu_rrd_create_file: Successfully created RRD file \"%s\".",
- filename);
+ status = srrd_create (filename, stepsize, last_up,
+ argc, (const char **) argv);
+
+ if (status != 0)
+ {
+ WARNING ("cu_rrd_create_file: srrd_create (%s) returned status %i.",
+ filename, status);
+ }
+ else
+ {
+ DEBUG ("cu_rrd_create_file: Successfully created RRD file \"%s\".",
+ filename);
+ }
}
+ free (argv);
+ ds_free (ds_num, ds_def);
+ rra_free (rra_num, rra_def);
+
return (status);
} /* }}} int cu_rrd_create_file */