Merge branch 'collectd-4.3'
[collectd.git] / src / plugin.c
index 0570f0e..dfab52c 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/plugin.c
- * Copyright (C) 2005,2006  Florian octo Forster
+ * Copyright (C) 2005-2008  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
@@ -17,6 +17,7 @@
  *
  * Authors:
  *   Florian octo Forster <octo at verplant.org>
+ *   Sebastian Harl <sh at tokkee.org>
  **/
 
 #include "collectd.h"
@@ -53,6 +54,7 @@ typedef struct read_func_s read_func_t;
 static llist_t *list_init;
 static llist_t *list_read;
 static llist_t *list_write;
+static llist_t *list_flush;
 static llist_t *list_shutdown;
 static llist_t *list_log;
 static llist_t *list_notification;
@@ -312,7 +314,7 @@ int plugin_load (const char *type)
 {
        DIR  *dh;
        const char *dir;
-       char  filename[BUFSIZE];
+       char  filename[BUFSIZE] = "";
        char  typename[BUFSIZE];
        int   typename_len;
        int   ret;
@@ -326,7 +328,8 @@ int plugin_load (const char *type)
 
        /* `cpu' should not match `cpufreq'. To solve this we add `.so' to the
         * type when matching the filename */
-       if (snprintf (typename, BUFSIZE, "%s.so", type) >= BUFSIZE)
+       if (ssnprintf (typename, sizeof (typename),
+                       "%s.so", type) >= sizeof (typename))
        {
                WARNING ("snprintf: truncated: `%s.so'", type);
                return (-1);
@@ -346,7 +349,8 @@ int plugin_load (const char *type)
                if (strncasecmp (de->d_name, typename, typename_len))
                        continue;
 
-               if (snprintf (filename, BUFSIZE, "%s/%s", dir, de->d_name) >= BUFSIZE)
+               if (ssnprintf (filename, sizeof (filename),
+                               "%s/%s", dir, de->d_name) >= sizeof (filename))
                {
                        WARNING ("snprintf: truncated: `%s/%s'", dir, de->d_name);
                        continue;
@@ -379,6 +383,9 @@ int plugin_load (const char *type)
 
        closedir (dh);
 
+       if (filename[0] == '\0')
+               fprintf (stderr, "Could not find plugin %s.\n", type);
+
        return (ret);
 }
 
@@ -434,6 +441,11 @@ int plugin_register_write (const char *name,
        return (register_callback (&list_write, name, (void *) callback));
 } /* int plugin_register_write */
 
+int plugin_register_flush (const char *name, int (*callback) (const int))
+{
+       return (register_callback (&list_flush, name, (void *) callback));
+} /* int plugin_register_flush */
+
 int plugin_register_shutdown (char *name,
                int (*callback) (void))
 {
@@ -528,6 +540,11 @@ int plugin_unregister_write (const char *name)
        return (plugin_unregister (list_write, name));
 }
 
+int plugin_unregister_flush (const char *name)
+{
+       return (plugin_unregister (list_flush, name));
+}
+
 int plugin_unregister_shutdown (const char *name)
 {
        return (plugin_unregister (list_shutdown, name));
@@ -640,6 +657,43 @@ void plugin_read_all (void)
        pthread_mutex_unlock (&read_lock);
 } /* void plugin_read_all */
 
+int plugin_flush_one (int timeout, const char *name)
+{
+       int (*callback) (int);
+       llentry_t *le;
+       int status;
+
+       if (list_flush == NULL)
+               return (-1);
+
+       le = llist_search (list_flush, name);
+       if (le == NULL)
+               return (-1);
+       callback = (int (*) (int)) le->value;
+
+       status = (*callback) (timeout);
+
+       return (status);
+} /* int plugin_flush_ont */
+
+void plugin_flush_all (int timeout)
+{
+       int (*callback) (int);
+       llentry_t *le;
+
+       if (list_flush == NULL)
+               return;
+
+       le = llist_head (list_flush);
+       while (le != NULL)
+       {
+               callback = (int (*) (int)) le->value;
+               le = le->next;
+
+               (*callback) (timeout);
+       }
+} /* void plugin_flush_all */
+
 void plugin_shutdown_all (void)
 {
        int (*callback) (void);
@@ -665,36 +719,63 @@ void plugin_shutdown_all (void)
        }
 } /* void plugin_shutdown_all */
 
-int plugin_dispatch_values (const char *name, value_list_t *vl)
+int plugin_dispatch_values (value_list_t *vl)
 {
        int (*callback) (const data_set_t *, const value_list_t *);
        data_set_t *ds;
        llentry_t *le;
 
-       if ((list_write == NULL) || (data_sets == NULL))
+       if ((vl == NULL) || (*vl->type == '\0')) {
+               ERROR ("plugin_dispatch_values: Invalid value list.");
                return (-1);
+       }
 
-       if (c_avl_get (data_sets, name, (void *) &ds) != 0)
+       if (list_write == NULL)
        {
-               DEBUG ("No such dataset registered: %s", name);
+               ERROR ("plugin_dispatch_values: No write callback has been "
+                               "registered. Please load at least one plugin "
+                               "that provides a write function.");
+               return (-1);
+       }
+
+       if (data_sets == NULL)
+       {
+               ERROR ("plugin_dispatch_values: No data sets registered. "
+                               "Could the types database be read? Check "
+                               "your `TypesDB' setting!");
                return (-1);
        }
 
-       DEBUG ("plugin: plugin_dispatch_values: time = %u; interval = %i; "
+       if (c_avl_get (data_sets, vl->type, (void *) &ds) != 0)
+       {
+               INFO ("plugin_dispatch_values: Dataset not found: %s", vl->type);
+               return (-1);
+       }
+
+       DEBUG ("plugin_dispatch_values: time = %u; interval = %i; "
                        "host = %s; "
                        "plugin = %s; plugin_instance = %s; "
                        "type = %s; type_instance = %s;",
                        (unsigned int) vl->time, vl->interval,
                        vl->host,
                        vl->plugin, vl->plugin_instance,
-                       ds->type, vl->type_instance);
+                       vl->type, vl->type_instance);
+
+#if COLLECT_DEBUG
+       assert (0 == strcmp (ds->type, vl->type));
+#else
+       if (0 != strcmp (ds->type, vl->type))
+               WARNING ("plugin_dispatch_values: (ds->type = %s) != (vl->type = %s)",
+                               ds->type, vl->type);
+#endif
 
 #if COLLECT_DEBUG
        assert (ds->ds_num == vl->values_len);
 #else
        if (ds->ds_num != vl->values_len)
        {
-               ERROR ("plugin: ds->type = %s: (ds->ds_num = %i) != "
+               ERROR ("plugin_dispatch_values: ds->type = %s: "
+                               "(ds->ds_num = %i) != "
                                "(vl->values_len = %i)",
                                ds->type, ds->ds_num, vl->values_len);
                return (-1);
@@ -704,6 +785,7 @@ int plugin_dispatch_values (const char *name, value_list_t *vl)
        escape_slashes (vl->host, sizeof (vl->host));
        escape_slashes (vl->plugin, sizeof (vl->plugin));
        escape_slashes (vl->plugin_instance, sizeof (vl->plugin_instance));
+       escape_slashes (vl->type, sizeof (vl->type));
        escape_slashes (vl->type_instance, sizeof (vl->type_instance));
 
        /* Update the value cache */