X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fdaemon%2Fplugin.c;h=6ef2f2a44cb55a72965bbbc6e77d6ed470427fc8;hb=6286127470b83578c2889db546cfa32cb0fe0147;hp=e7d4e8df2c801b7e6d0a0e6a8bdd4e120cedbf20;hpb=d5565943cd7ee338e5b750a027faff8115df4c72;p=collectd.git diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c index e7d4e8df..6ef2f2a4 100644 --- a/src/daemon/plugin.c +++ b/src/daemon/plugin.c @@ -80,6 +80,12 @@ struct write_queue_s write_queue_t *next; }; +struct flush_callback_s { + char *name; + cdtime_t timeout; +}; +typedef struct flush_callback_s flush_callback_t; + /* * Private variables */ @@ -282,7 +288,7 @@ static int register_callback (llist_t **list, /* {{{ */ { ERROR ("plugin: register_callback: " "llentry_create failed."); - free (key); + sfree (key); destroy_callback (cf); return (-1); } @@ -352,9 +358,9 @@ static void log_list_callbacks (llist_t **list, /* {{{ */ *str = '\0'; strjoin(str, len, keys, n, "', '"); INFO("%s ['%s']", comment, str); - free(str); + sfree (str); } - free(keys); + sfree (keys); } /* }}} void log_list_callbacks */ static int create_register_callback (llist_t **list, /* {{{ */ @@ -477,7 +483,9 @@ static void *plugin_read_thread (void __attribute__((unused)) *args) { read_func_t *rf; plugin_ctx_t old_ctx; + cdtime_t start; cdtime_t now; + cdtime_t elapsed; int status; int rf_type; int rc; @@ -556,6 +564,8 @@ static void *plugin_read_thread (void __attribute__((unused)) *args) DEBUG ("plugin_read_thread: Handling `%s'.", rf->rf_name); + start = cdtime (); + old_ctx = plugin_set_ctx (rf->rf_ctx); if (rf_type == RF_SIMPLE) @@ -599,8 +609,22 @@ static void *plugin_read_thread (void __attribute__((unused)) *args) /* update the ``next read due'' field */ now = cdtime (); + /* calculate the time spent in the read function */ + elapsed = (now - start); + + if (elapsed > rf->rf_effective_interval) + WARNING ("plugin_read_thread: read-function of the `%s' plugin took %.3f " + "seconds, which is above its read interval (%.3f seconds). You might " + "want to adjust the `Interval' or `ReadThreads' settings.", + rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed), + CDTIME_T_TO_DOUBLE(rf->rf_effective_interval)); + + DEBUG ("plugin_read_thread: read-function of the `%s' plugin took " + "%.6f seconds.", + rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed)); + DEBUG ("plugin_read_thread: Effective interval of the " - "%s plugin is %.3f seconds.", + "`%s' plugin is %.3f seconds.", rf->rf_name, CDTIME_T_TO_DOUBLE (rf->rf_effective_interval)); @@ -617,7 +641,7 @@ static void *plugin_read_thread (void __attribute__((unused)) *args) rf->rf_next_read = now; } - DEBUG ("plugin_read_thread: Next read of the %s plugin at %.3f.", + DEBUG ("plugin_read_thread: Next read of the `%s' plugin at %.3f.", rf->rf_name, CDTIME_T_TO_DOUBLE (rf->rf_next_read)); @@ -883,7 +907,7 @@ static void start_write_threads (size_t num) /* {{{ */ static void stop_write_threads (void) /* {{{ */ { write_queue_t *q; - int i; + size_t i; if (write_threads == NULL) return; @@ -924,7 +948,7 @@ static void stop_write_threads (void) /* {{{ */ if (i > 0) { - WARNING ("plugin: %i value list%s left after shutting down " + WARNING ("plugin: %zu value list%s left after shutting down " "the write threads.", i, (i == 1) ? " was" : "s were"); } @@ -935,17 +959,17 @@ static void stop_write_threads (void) /* {{{ */ */ void plugin_set_dir (const char *dir) { - if (plugindir != NULL) - free (plugindir); + sfree (plugindir); if (dir == NULL) - plugindir = NULL; - else if ((plugindir = strdup (dir)) == NULL) { - char errbuf[1024]; - ERROR ("strdup failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); + plugindir = NULL; + return; } + + plugindir = strdup (dir); + if (plugindir == NULL) + ERROR ("plugin_set_dir: strdup(\"%s\") failed", dir); } static _Bool plugin_is_loaded (char const *name) @@ -1083,6 +1107,7 @@ int plugin_load (char const *plugin_name, uint32_t flags) /* success */ plugin_mark_loaded (plugin_name); ret = 0; + INFO ("plugin_load: plugin \"%s\" successfully loaded.", plugin_name); break; } else @@ -1247,7 +1272,7 @@ int plugin_register_read (const char *name, int plugin_register_complex_read (const char *group, const char *name, plugin_read_cb callback, - const struct timespec *interval, + cdtime_t interval, user_data_t *user_data) { read_func_t *rf; @@ -1268,10 +1293,7 @@ int plugin_register_complex_read (const char *group, const char *name, rf->rf_group[0] = '\0'; rf->rf_name = strdup (name); rf->rf_type = RF_COMPLEX; - if (interval != NULL) - rf->rf_interval = TIMESPEC_TO_CDTIME_T (interval); - else - rf->rf_interval = plugin_get_interval (); + rf->rf_interval = (interval != 0) ? interval : plugin_get_interval (); /* Set user data */ if (user_data == NULL) @@ -1302,11 +1324,105 @@ int plugin_register_write (const char *name, (void *) callback, ud)); } /* int plugin_register_write */ +static int plugin_flush_timeout_callback (user_data_t *ud) +{ + flush_callback_t *cb = ud->data; + + return plugin_flush (cb->name, cb->timeout, /* identifier = */ NULL); +} /* static int plugin_flush_callback */ + +static void plugin_flush_timeout_callback_free (void *data) +{ + flush_callback_t *cb = data; + + if (cb == NULL) return; + + sfree (cb->name); + sfree (cb); +} /* static void plugin_flush_callback_free */ + +static char *plugin_flush_callback_name (const char *name) +{ + char *flush_prefix = "flush/"; + size_t prefix_size; + char *flush_name; + size_t name_size; + + prefix_size = strlen(flush_prefix); + name_size = strlen(name); + + flush_name = malloc (sizeof(char) * (name_size + prefix_size + 1)); + if (flush_name == NULL) + { + ERROR ("plugin_flush_callback_name: malloc failed."); + return (NULL); + } + + sstrncpy (flush_name, flush_prefix, prefix_size + 1); + sstrncpy (flush_name + prefix_size, name, name_size + 1); + + return flush_name; +} /* static char *plugin_flush_callback_name */ + int plugin_register_flush (const char *name, plugin_flush_cb callback, user_data_t *ud) { - return (create_register_callback (&list_flush, name, - (void *) callback, ud)); + int status; + plugin_ctx_t ctx = plugin_get_ctx (); + + status = create_register_callback (&list_flush, name, + (void *) callback, ud); + if (status != 0) + return status; + + if (ctx.flush_interval != 0) + { + char *flush_name; + user_data_t ud; + flush_callback_t *cb; + + flush_name = plugin_flush_callback_name (name); + if (flush_name == NULL) + return (-1); + + cb = malloc(sizeof(flush_callback_t)); + if (cb == NULL) + { + ERROR ("plugin_register_flush: malloc failed."); + sfree (flush_name); + return (-1); + } + + cb->name = strdup (name); + if (cb->name == NULL) + { + ERROR ("plugin_register_flush: strdup failed."); + sfree (cb); + sfree (flush_name); + return (-1); + } + cb->timeout = ctx.flush_timeout; + + ud.data = cb; + ud.free_func = plugin_flush_timeout_callback_free; + + status = plugin_register_complex_read ( + /* group = */ "flush", + /* name = */ flush_name, + /* callback = */ plugin_flush_timeout_callback, + /* interval = */ ctx.flush_interval, + /* user data = */ &ud); + + sfree (flush_name); + if (status != 0) + { + sfree (cb->name); + sfree (cb); + return status; + } + } + + return 0; } /* int plugin_register_flush */ int plugin_register_missing (const char *name, @@ -1347,7 +1463,7 @@ static void plugin_free_data_sets (void) int plugin_register_data_set (const data_set_t *ds) { data_set_t *ds_copy; - int i; + size_t i; if ((data_sets != NULL) && (c_avl_get (data_sets, ds->type, NULL) == 0)) @@ -1371,7 +1487,7 @@ int plugin_register_data_set (const data_set_t *ds) * ds->ds_num); if (ds_copy->ds == NULL) { - free (ds_copy); + sfree (ds_copy); return (-1); } @@ -1525,7 +1641,21 @@ int plugin_unregister_write (const char *name) int plugin_unregister_flush (const char *name) { - return (plugin_unregister (list_flush, name)); + plugin_ctx_t ctx = plugin_get_ctx (); + + if (ctx.flush_interval != 0) + { + char *flush_name; + + flush_name = plugin_flush_callback_name (name); + if (flush_name != NULL) + { + plugin_unregister_read(flush_name); + sfree (flush_name); + } + } + + return plugin_unregister (list_flush, name); } int plugin_unregister_missing (const char *name) @@ -1567,7 +1697,6 @@ int plugin_unregister_notification (const char *name) void plugin_init_all (void) { char const *chain_name; - long write_threads_num; llentry_t *le; int status; @@ -2031,8 +2160,8 @@ static int plugin_dispatch_values_internal (value_list_t *vl) if (ds->ds_num != vl->values_len) { ERROR ("plugin_dispatch_values: ds->type = %s: " - "(ds->ds_num = %i) != " - "(vl->values_len = %i)", + "(ds->ds_num = %zu) != " + "(vl->values_len = %zu)", ds->type, ds->ds_num, vl->values_len); return (-1); } @@ -2085,7 +2214,7 @@ static int plugin_dispatch_values_internal (value_list_t *vl) * don't get confused.. */ if (saved_values != NULL) { - free (vl->values); + sfree (vl->values); vl->values = saved_values; vl->values_len = saved_values_len; } @@ -2114,7 +2243,7 @@ static int plugin_dispatch_values_internal (value_list_t *vl) * confused.. */ if (saved_values != NULL) { - free (vl->values); + sfree (vl->values); vl->values = saved_values; vl->values_len = saved_values_len; } @@ -2272,7 +2401,7 @@ int plugin_dispatch_multivalue (value_list_t const *template, /* {{{ */ case DS_TYPE_GAUGE: vl->values[0].gauge = va_arg (ap, gauge_t); if (store_percentage) - vl->values[0].gauge *= 100.0 / sum; + vl->values[0].gauge *= sum ? (100.0 / sum) : 0; break; case DS_TYPE_ABSOLUTE: vl->values[0].absolute = va_arg (ap, absolute_t); @@ -2600,7 +2729,11 @@ int plugin_notification_meta_free (notification_meta_t *n) if (this->type == NM_TYPE_STRING) { - free ((char *)this->nm_value.nm_string); + /* Assign to a temporary variable to work around nm_string's const + * modifier. */ + void *tmp = (void *) this->nm_value.nm_string; + + sfree (tmp); this->nm_value.nm_string = NULL; } sfree (this); @@ -2707,7 +2840,7 @@ static void *plugin_thread_start (void *arg) plugin_set_ctx (plugin_thread->ctx); - free (plugin_thread); + sfree (plugin_thread); return start_routine (plugin_arg); } /* void *plugin_thread_start */