+static void *plugin_read_thread (void *args)
+{
+ llentry_t *le;
+ read_func_t *rf;
+ int status;
+ int done;
+
+ pthread_mutex_lock (&read_lock);
+
+ while (read_loop != 0)
+ {
+ le = llist_head (list_read);
+ done = 0;
+
+ while ((read_loop != 0) && (le != NULL))
+ {
+ rf = (read_func_t *) le->value;
+
+ if (rf->needs_read != TODO)
+ {
+ le = le->next;
+ continue;
+ }
+
+ /* We will do this read function */
+ rf->needs_read = ACTIVE;
+
+ DEBUG ("[thread #%5lu] plugin: plugin_read_thread: Handling %s",
+ (unsigned long int) pthread_self (), le->key);
+ pthread_mutex_unlock (&read_lock);
+
+ status = rf->callback ();
+ done++;
+
+ if (status != 0)
+ {
+ if (rf->wait_time < interval_g)
+ rf->wait_time = interval_g;
+ rf->wait_left = rf->wait_time;
+ rf->wait_time = rf->wait_time * 2;
+ if (rf->wait_time > 86400)
+ rf->wait_time = 86400;
+
+ NOTICE ("read-function of plugin `%s' "
+ "failed. Will suspend it for %i "
+ "seconds.", le->key, rf->wait_left);
+ }
+ else
+ {
+ rf->wait_left = 0;
+ rf->wait_time = interval_g;
+ }
+
+ pthread_mutex_lock (&read_lock);
+
+ rf->needs_read = DONE;
+ le = le->next;
+ } /* while (le != NULL) */
+
+ if ((read_loop != 0) && (done == 0))
+ {
+ DEBUG ("[thread #%5lu] plugin: plugin_read_thread: Waiting on read_cond.",
+ (unsigned long int) pthread_self ());
+ pthread_cond_wait (&read_cond, &read_lock);
+ }
+ } /* while (read_loop) */
+
+ pthread_mutex_unlock (&read_lock);
+
+ pthread_exit (NULL);
+} /* void *plugin_read_thread */
+
+static void start_threads (int num)
+{
+ int i;
+
+ if (read_threads != NULL)
+ return;
+
+ read_threads = (pthread_t *) calloc (num, sizeof (pthread_t));
+ if (read_threads == NULL)
+ {
+ ERROR ("plugin: start_threads: calloc failed.");
+ return;
+ }
+
+ read_threads_num = 0;
+ for (i = 0; i < num; i++)
+ {
+ if (pthread_create (read_threads + read_threads_num, NULL,
+ plugin_read_thread, NULL) == 0)
+ {
+ read_threads_num++;
+ }
+ else
+ {
+ ERROR ("plugin: start_threads: pthread_create failed.");
+ return;
+ }
+ } /* for (i) */
+} /* void start_threads */
+
+static void stop_threads (void)
+{
+ int i;
+
+ pthread_mutex_lock (&read_lock);
+ read_loop = 0;
+ DEBUG ("plugin: stop_threads: Signalling `read_cond'");
+ pthread_cond_broadcast (&read_cond);
+ pthread_mutex_unlock (&read_lock);
+
+ for (i = 0; i < read_threads_num; i++)
+ {
+ if (pthread_join (read_threads[i], NULL) != 0)
+ {
+ ERROR ("plugin: stop_threads: pthread_join failed.");
+ }
+ read_threads[i] = (pthread_t) 0;
+ }
+ sfree (read_threads);
+ read_threads_num = 0;
+} /* void stop_threads */
+
+/*
+ * 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)
+ {
+ char errbuf[1024];
+ ERROR ("strdup failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ }
+}
+