From ae8e8fdb8913818a33e9bf139c55fbe448c3a105 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Wed, 6 Dec 2006 18:43:56 +0100 Subject: [PATCH] plugins: Implement a first version of the new plugin mechanismn. Instead of the impractical `plugin_register' function, provide a variety of different register functions, so plugin can `hook in' at various stages of the daemon. The most important new hook is likely the `write' hook which will allow for generic `output plugins' to be plugged in. --- src/collectd.c | 3 + src/configfile.c | 14 +-- src/configfile.h | 8 +- src/plugin.c | 336 ++++++++++++++++++++++--------------------------------- src/plugin.h | 123 +++++++++++--------- 5 files changed, 221 insertions(+), 263 deletions(-) diff --git a/src/collectd.c b/src/collectd.c index a1e15bf1..6e711108 100644 --- a/src/collectd.c +++ b/src/collectd.c @@ -224,6 +224,8 @@ static int start_client (void) static int start_server (void) { /* FIXME use stack here! */ + /* FIXME */ +#if 0 char *host; char *type; char *instance; @@ -240,6 +242,7 @@ static int start_server (void) if (values != NULL) free (values); values = NULL; } +#endif return (0); } /* static int start_server (void) */ #endif /* HAVE_LIBRRD */ diff --git a/src/configfile.c b/src/configfile.c index 40b46fab..8fe42876 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -50,9 +50,9 @@ extern int operating_mode; typedef struct cf_callback { - char *type; - int (*callback) (char *, char *); - char **keys; + const char *type; + int (*callback) (const char *, const char *); + const char **keys; int keys_num; struct cf_callback *next; } cf_callback_t; @@ -152,7 +152,7 @@ static int cf_dispatch (char *type, const char *orig_key, const char *orig_value return (ret); } -void cf_unregister (char *type) +void cf_unregister (const char *type) { cf_callback_t *this, *prev; @@ -171,9 +171,9 @@ void cf_unregister (char *type) } } -void cf_register (char *type, - int (*callback) (char *, char *), - char **keys, int keys_num) +void cf_register (const char *type, + int (*callback) (const char *, const char *), + const char **keys, int keys_num) { cf_callback_t *cf_cb; char buf[64]; diff --git a/src/configfile.h b/src/configfile.h index 0bb11b2a..fec1cf4b 100644 --- a/src/configfile.h +++ b/src/configfile.h @@ -31,7 +31,7 @@ * `type' Name of the plugin (must be the same as passed to * `plugin_register' */ -void cf_unregister (char *type); +void cf_unregister (const char *type); /* * DESCRIPTION @@ -57,9 +57,9 @@ void cf_unregister (char *type); * exists for each `type' at any time. This means that `cf_register' may be * called multiple times, but only the last call will have an effect. */ -void cf_register (char *type, - int (*callback) (char *, char *), - char **keys, int keys_num); +void cf_register (const char *type, + int (*callback) (const char *, const char *), + const char **keys, int keys_num); /* * DESCRIPTION diff --git a/src/plugin.c b/src/plugin.c index 46a1c617..310cb706 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -25,26 +25,25 @@ #include #include "plugin.h" -#include "network.h" +#include "configfile.h" +#include "utils_llist.h" #include "utils_debug.h" -typedef struct plugin -{ - char *type; - void (*init) (void); - void (*read) (void); - void (*write) (char *host, char *inst, char *val); - void (*shutdown) (void); - struct plugin *next; -} plugin_t; - -static plugin_t *first_plugin = NULL; - -extern int operating_mode; +/* + * Private variables + */ +static llist_t *list_init; +static llist_t *list_read; +static llist_t *list_write; +static llist_t *list_shutdown; +static llist_t *list_data_set; static char *plugindir = NULL; -char *plugin_get_dir (void) +/* + * Static functions + */ +static const char *plugin_get_dir (void) { if (plugindir == NULL) return (PLUGINDIR); @@ -52,66 +51,37 @@ char *plugin_get_dir (void) return (plugindir); } -void plugin_set_dir (const char *dir) +static int register_callback (llist_t **list, const char *name, void *callback) { - if (plugindir != NULL) - free (plugindir); + llentry_t *le; - if (dir == NULL) - plugindir = NULL; - else if ((plugindir = strdup (dir)) == NULL) - syslog (LOG_ERR, "strdup: %s", strerror (errno)); -} - -/* - * Returns the number of plugins registered - */ -int plugin_count (void) -{ - int i; - plugin_t *p; - - for (i = 0, p = first_plugin; p != NULL; p = p->next) - i++; - - return (i); -} - -/* - * Returns the plugins with the type `type' or NULL if it's not found. - */ -plugin_t *plugin_search (const char *type) -{ - plugin_t *ret; - - if (type == NULL) - return (NULL); - - for (ret = first_plugin; ret != NULL; ret = ret->next) - if (strcmp (ret->type, type) == 0) - break; + if ((*list == NULL) + && ((*list = llist_create ()) == NULL)) + return (-1); - return (ret); -} + le = llist_search (*list, name); + if (le == NULL) + { + le = llentry_create (name, callback); + if (le == NULL) + return (-1); -/* - * Returns true if the plugin is loaded (i.e. `exists') and false otherwise. - * This is used in `configfile.c' to skip sections that are not needed.. - */ -int plugin_exists (char *type) -{ - if (plugin_search (type) == NULL) - return (0); + llist_append (*list, le); + } else - return (1); -} + { + le->value = callback; + } + + return (0); +} /* int register_callback */ /* * (Try to) load the shared object `file'. Won't complain if it isn't a shared * object, but it will bitch about a shared object not having a * ``module_register'' symbol.. */ -int plugin_load_file (char *file) +static int plugin_load_file (char *file) { lt_dlhandle dlh; void (*reg_handle) (void); @@ -143,11 +113,25 @@ int plugin_load_file (char *file) return (0); } +/* + * Public functions + */ +void plugin_set_dir (const char *dir) +{ + if (plugindir != NULL) + free (plugindir); + + if (dir == NULL) + plugindir = NULL; + else if ((plugindir = strdup (dir)) == NULL) + syslog (LOG_ERR, "strdup failed: %s", strerror (errno)); +} + #define BUFSIZE 512 int plugin_load (const char *type) { DIR *dh; - char *dir; + const char *dir; char filename[BUFSIZE]; char typename[BUFSIZE]; int typename_len; @@ -160,10 +144,6 @@ int plugin_load (const char *type) dir = plugin_get_dir (); ret = 1; - /* don't load twice */ - if (plugin_search (type) != NULL) - return (0); - /* `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) @@ -215,170 +195,124 @@ int plugin_load (const char *type) } /* - * (Try to) load all plugins in `dir'. Returns the number of loaded plugins.. + * The `register_*' functions follow */ -int plugin_load_all (char *dir) +int plugin_register_config (const char *name, + int (*callback) (const char *key, const char *val), + const char **keys, int keys_num) { - DIR *dh; - struct dirent *de; - char filename[BUFSIZE]; - struct stat statbuf; - - if (dir == NULL) - dir = plugin_get_dir (); - else - plugin_set_dir (dir); - - if ((dh = opendir (dir)) == NULL) - { - syslog (LOG_ERR, "opendir (%s): %s", dir, strerror (errno)); - return (0); - } + cf_register (name, callback, keys, keys_num); + return (0); +} /* int plugin_register_config */ - while ((de = readdir (dh)) != NULL) - { - if (snprintf (filename, BUFSIZE, "%s/%s", dir, de->d_name) >= BUFSIZE) - { - syslog (LOG_WARNING, "snprintf: truncated: %s/%s", dir, de->d_name); - continue; - } +int plugin_register_init (const char *name, + int (*callback) (void)) +{ + return (register_callback (&list_init, name, (void *) callback)); +} /* plugin_register_init */ - if (lstat (filename, &statbuf) == -1) - { - syslog (LOG_WARNING, "stat %s: %s", filename, strerror (errno)); - continue; - } - else if (!S_ISREG (statbuf.st_mode)) - { - continue; - } +int plugin_register_read (const char *name, + int (*callback) (void)) +{ + return (register_callback (&list_read, name, (void *) callback)); +} /* int plugin_register_read */ - plugin_load_file (filename); - } +int plugin_register_write (const char *name, + int (*callback) (const data_set_t *ds, const value_list_t *vl)) +{ + return (register_callback (&list_write, name, (void *) callback)); +} /* int plugin_register_write */ - closedir (dh); +int plugin_register_shutdown (char *name, + int (*callback) (void)) +{ + return (register_callback (&list_shutdown, name, (void *) callback)); +} /* int plugin_register_shutdown */ - return (plugin_count ()); -} -#undef BUFSIZE +int plugin_register_data_set (const data_set_t *ds) +{ + return (register_callback (&list_data_set, ds->type, (void *) ds)); +} /* int plugin_register_data_set */ -/* - * Call `init' on all plugins (if given) - */ void plugin_init_all (void) { - plugin_t *p; + int (*callback) (void); + llentry_t *le; - for (p = first_plugin; p != NULL; p = p->next) - if (p->init != NULL) - (*p->init) (); -} + if (list_init == NULL) + return; -/* - * Call `read' on all plugins (if given) - */ -void plugin_read_all (const int *loop) -{ - plugin_t *p; + le = llist_head (list_init); + while (le != NULL) + { + callback = le->value; + (*callback) (); - for (p = first_plugin; (*loop == 0) && (p != NULL); p = p->next) - if (p->read != NULL) - (*p->read) (); -} + le = le->next; + } +} /* void plugin_init_all */ -/* - * Call `shutdown' on all plugins (if given) - */ -void plugin_shutdown_all (void) +void plugin_read_all (const int *loop) { - plugin_t *p; + int (*callback) (void); + llentry_t *le; - for (p = first_plugin; NULL != p; p = p->next) - if (NULL != p->shutdown) - (*p->shutdown) (); - return; -} + if (list_read == NULL) + return; -/* - * Add plugin to the linked list of registered plugins. - */ -void plugin_register (char *type, - void (*init) (void), - void (*read) (void), - void (*write) (char *, char *, char *)) -{ - plugin_t *p; + le = llist_head (list_read); + while ((*loop == 0) && (le != NULL)) + { + callback = le->value; + (*callback) (); - if (plugin_search (type) != NULL) - return; + le = le->next; + } +} /* void plugin_read_all */ -#ifdef HAVE_LIBRRD - if (operating_mode != MODE_SERVER) -#endif - if ((init != NULL) && (read == NULL)) - syslog (LOG_NOTICE, "Plugin `%s' doesn't provide a read function.", type); +void plugin_shutdown_all (void) +{ + int (*callback) (void); + llentry_t *le; - if ((p = (plugin_t *) malloc (sizeof (plugin_t))) == NULL) + if (list_shutdown == NULL) return; - if ((p->type = strdup (type)) == NULL) + le = llist_head (list_shutdown); + while (le != NULL) { - free (p); - return; - } - - p->init = init; - p->read = read; - p->write = write; - - p->shutdown = NULL; + callback = le->value; + (*callback) (); - p->next = first_plugin; - first_plugin = p; -} + le = le->next; + } +} /* void plugin_shutdown_all */ -/* - * Register the shutdown function (optional). - */ -int plugin_register_shutdown (char *type, void (*shutdown) (void)) +int plugin_dispatch_values (const char *name, const value_list_t *vl) { - plugin_t *p = plugin_search (type); + int (*callback) (const data_set_t *, const value_list_t *); + data_set_t *ds; + llentry_t *le; - if (NULL == p) - return -1; - - p->shutdown = shutdown; - return 0; -} + if (list_write == NULL) + return (-1); -/* - * Send received data back to the plugin/module which will append DS - * definitions and pass it on to ``rrd_update_file''. - */ -void plugin_write (char *host, char *type, char *inst, char *val) -{ - plugin_t *p; + le = llist_search (list_data_set, name); + if (le == NULL) + return (-1); - if ((p = plugin_search (type)) == NULL) - return; + ds = (data_set_t *) le->value; - if (p->write == NULL) - return; + le = llist_head (list_write); + while (le != NULL) + { + callback = le->value; + (*callback) (ds, vl); - (*p->write) (host, inst, val); -} + le = le->next; + } -/* - * Receive data from the plugin/module and get it somehow to ``plugin_write'': - * Either using ``network_send'' (when in network/client mode) or call it - * directly (in local mode). - */ -void plugin_submit (char *type, char *inst, char *val) -{ - if (operating_mode == MODE_CLIENT) - network_send (type, inst, val); - else - plugin_write (NULL, type, inst, val); + return (0); } void plugin_complain (int level, complain_t *c, const char *format, ...) diff --git a/src/plugin.h b/src/plugin.h index 45e9b494..93bf0294 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -23,9 +23,52 @@ * Florian octo Forster **/ +#define DATA_MAX_NAME_LEN 64 + +#define DS_TYPE_COUNTER 0 +#define DS_TYPE_GAUGE 1 + /* - * + * Public data types */ +typedef unsigned long long counter_t; +typedef double gauge_t; + +union value_u +{ + counter_t counter; + gauge_t gauge; +}; +typedef union value_u value_t; + +struct value_list_s +{ + value_t *values; + int values_len; + char plugin[DATA_MAX_NAME_LEN]; + char plugin_instance[DATA_MAX_NAME_LEN]; + char type_instance[DATA_MAX_NAME_LEN]; +}; +typedef struct value_list_s value_list_t; + +struct data_source_s +{ + char name[DATA_MAX_NAME_LEN]; + int type; + double min; + double max; +}; +typedef struct data_source_s data_source_t; + +struct data_set_s +{ + char type[DATA_MAX_NAME_LEN]; + int ds_num; + data_source_t *ds; + char *filename; +}; +typedef struct data_set_s data_set_t; + typedef struct complain_s { unsigned int interval; /* how long we wait for reporting this error again */ @@ -49,34 +92,6 @@ void plugin_set_dir (const char *dir); /* * NAME - * plugin_count - * - * DESCRIPTION - * trivial - * - * RETURN VALUE - * The number of currently loaded plugins - */ -int plugin_count (void); - -/* - * NAME - * plugin_exists - * - * DESCRIPTION - * trivial - * - * ARGUMENTS - * `type' Name of the plugin. - * - * RETURN VALUE - * Returns non-zero if a plugin with the name $type is found and zero - * otherwise. - */ -int plugin_exists (char *type); - -/* - * NAME * plugin_load * * DESCRIPTION @@ -95,42 +110,48 @@ int plugin_exists (char *type); * NOTES * No attempt is made to re-load an already loaded module. */ -int plugin_load (const char *type); +int plugin_load (const char *name); -int plugin_load_all (char *dir); void plugin_init_all (void); void plugin_read_all (const int *loop); - void plugin_shutdown_all (void); -void plugin_register (char *type, - void (*init) (void), - void (*read) (void), - void (*write) (char *, char *, char *)); - -int plugin_register_shutdown (char *, void (*) (void)); +/* + * The `plugin_register_*' functions are used to make `config', `init', + * `read', `write' and `shutdown' functions known to the plugin + * infrastructure. Also, the data-formats are made public like this. + */ +int plugin_register_config (const char *name, + int (*callback) (const char *key, const char *val), + const char **keys, int keys_num); +int plugin_register_init (const char *name, + int (*callback) (void)); +int plugin_register_read (const char *name, + int (*callback) (void)); +int plugin_register_write (const char *name, + int (*callback) (const data_set_t *ds, const value_list_t *vl)); +int plugin_register_shutdown (char *name, + int (*callback) (void)); +int plugin_register_data_set (const data_set_t *ds); /* * NAME - * plugin_write + * plugin_dispatch_values * * DESCRIPTION - * Searches the plugin for `type' in the plugin-list. If found, and a `write' - * function is registered, it's called. If either the plugin is not found or - * the plugin doesn't provide a `write' function this function will return - * without further notice. + * This function is called by reading processes with the values they've + * aquired. The function fetches the data-set definition (that has been + * registered using `plugin_register_data_set') and calls _all_ registered + * write-functions. * * ARGUMENTS - * `host' Host(name) from which the data originates. - * `type' Name of the plugin. - * `inst' Instance (passed to the plugin's `write' function. - * `val' Values for the RRD files. Also passed to the plugin. + * `name' Name/type of the data-set that describe the values in `vl'. + * `vl' Value list of the values that have been read by a `read' + * function. */ -void plugin_write (char *host, char *type, char *inst, char *val); - -void plugin_submit (char *type, char *inst, char *val); - +int plugin_dispatch_values (const char *name, const value_list_t *vl); +/* TODO: Move plugin_{complain,relief} into `utils_complain.[ch]'. -octo */ void plugin_complain (int level, complain_t *c, const char *format, ...); void plugin_relief (int level, complain_t *c, const char *format, ...); -- 2.11.0