/* do not automatically get the thread specific perl interpreter */
#define PERL_NO_GET_CONTEXT
+#define DONT_POISON_SPRINTF_YET 1
#include "collectd.h"
+#undef DONT_POISON_SPRINTF_YET
#include "configfile.h"
#include <EXTERN.h>
#include <perl.h>
+#if __GNUC__
+# pragma GCC poison sprintf
+#endif
+
#include <XSUB.h>
/* Some versions of Perl define their own version of DEBUG... :-/ */
#define PLUGIN_SHUTDOWN 3
#define PLUGIN_LOG 4
#define PLUGIN_NOTIF 5
+#define PLUGIN_FLUSH 6
-#define PLUGIN_TYPES 6
+#define PLUGIN_TYPES 7
#define PLUGIN_DATASET 255
static XS (Collectd_plugin_register_ds);
static XS (Collectd_plugin_unregister_ds);
static XS (Collectd_plugin_dispatch_values);
+static XS (Collectd__plugin_flush);
static XS (Collectd_plugin_dispatch_notification);
static XS (Collectd_plugin_log);
static XS (Collectd_call_by_name);
{ "Collectd::plugin_register_data_set", Collectd_plugin_register_ds },
{ "Collectd::plugin_unregister_data_set", Collectd_plugin_unregister_ds },
{ "Collectd::plugin_dispatch_values", Collectd_plugin_dispatch_values },
+ { "Collectd::_plugin_flush", Collectd__plugin_flush },
{ "Collectd::plugin_dispatch_notification",
Collectd_plugin_dispatch_notification },
{ "Collectd::plugin_log", Collectd_plugin_log },
{ "Collectd::TYPE_SHUTDOWN", PLUGIN_SHUTDOWN },
{ "Collectd::TYPE_LOG", PLUGIN_LOG },
{ "Collectd::TYPE_NOTIF", PLUGIN_NOTIF },
+ { "Collectd::TYPE_FLUSH", PLUGIN_FLUSH },
{ "Collectd::TYPE_DATASET", PLUGIN_DATASET },
{ "Collectd::DS_TYPE_COUNTER", DS_TYPE_COUNTER },
{ "Collectd::DS_TYPE_GAUGE", DS_TYPE_GAUGE },
sstrncpy (list.host, SvPV_nolen (*tmp), sizeof (list.host));
}
else {
- strcpy (list.host, hostname_g);
+ sstrncpy (list.host, hostname_g, sizeof (list.host));
}
if (NULL != (tmp = hv_fetch (values, "plugin", 6, 0)))
XPUSHs (sv_2mortal (newRV_noinc ((SV *)notif)));
}
+ else if (PLUGIN_FLUSH == type) {
+ /*
+ * $_[0] = $timeout;
+ * $_[1] = $identifier;
+ */
+ XPUSHs (sv_2mortal (newSViv (va_arg (ap, int))));
+ XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
+ }
PUTBACK;
} /* static XS (Collectd_plugin_dispatch_values) */
/*
+ * Collectd::_plugin_flush (plugin, timeout, identifier).
+ *
+ * plugin:
+ * name of the plugin to flush
+ *
+ * timeout:
+ * timeout to use when flushing the data
+ *
+ * identifier:
+ * data-set identifier to flush
+ */
+static XS (Collectd__plugin_flush)
+{
+ char *plugin = NULL;
+ int timeout = -1;
+ char *id = NULL;
+
+ dXSARGS;
+
+ if (3 != items) {
+ log_err ("Usage: Collectd::_plugin_flush(plugin, timeout, id)");
+ XSRETURN_EMPTY;
+ }
+
+ if (SvOK (ST (0)))
+ plugin = SvPV_nolen (ST (0));
+
+ if (SvOK (ST (1)))
+ timeout = (int)SvIV (ST (1));
+
+ if (SvOK (ST (2)))
+ id = SvPV_nolen (ST (2));
+
+ log_debug ("Collectd::_plugin_flush: plugin = \"%s\", timeout = %i, "
+ "id = \"%s\"", plugin, timeout, id);
+
+ if (0 == plugin_flush (plugin, timeout, id))
+ XSRETURN_YES;
+ else
+ XSRETURN_EMPTY;
+} /* static XS (Collectd__plugin_flush) */
+
+/*
* Collectd::plugin_dispatch_notification (notif).
*
* notif:
aTHX = t->interp;
- if (NULL != base) {
+ if ((NULL != base) && (NULL != PL_endav)) {
av_clear (PL_endav);
av_undef (PL_endav);
PL_endav = Nullav;
return pplugin_call_all (aTHX_ PLUGIN_NOTIF, notif);
} /* static int perl_notify (const notification_t *) */
+static int perl_flush (int timeout, const char *identifier)
+{
+ dTHX;
+
+ if (NULL == perl_threads)
+ return 0;
+
+ if (NULL == aTHX) {
+ c_ithread_t *t = NULL;
+
+ pthread_mutex_lock (&perl_threads->mutex);
+ t = c_ithread_create (perl_threads->head->interp);
+ pthread_mutex_unlock (&perl_threads->mutex);
+
+ aTHX = t->interp;
+ }
+ return pplugin_call_all (aTHX_ PLUGIN_FLUSH, timeout, identifier);
+} /* static int perl_flush (const int) */
+
static int perl_shutdown (void)
{
c_ithread_t *t = NULL;
plugin_unregister_init ("perl");
plugin_unregister_read ("perl");
plugin_unregister_write ("perl");
+ plugin_unregister_flush ("perl");
ret = pplugin_call_all (aTHX_ PLUGIN_SHUTDOWN);
log_err ("init_pi: pthread_key_create failed");
/* this must not happen - cowardly giving up if it does */
- exit (1);
+ return -1;
}
+#ifdef __FreeBSD__
+ /* On FreeBSD, PERL_SYS_INIT3 expands to some expression which
+ * triggers a "value computed is not used" warning by gcc. */
+ (void)
+#endif
PERL_SYS_INIT3 (&argc, &argv, &environ);
perl_threads = (c_ithread_list_t *)smalloc (sizeof (c_ithread_list_t));
if (0 != perl_parse (aTHX_ xs_init, argc, argv, NULL)) {
log_err ("init_pi: Unable to bootstrap Collectd.");
- exit (1);
+
+ perl_destruct (perl_threads->head->interp);
+ perl_free (perl_threads->head->interp);
+ sfree (perl_threads);
+
+ pthread_key_delete (perl_thr_key);
+ return -1;
}
/* Set $0 to "collectd" because perl_parse() has to set it to "-e". */
plugin_register_read ("perl", perl_read);
plugin_register_write ("perl", perl_write);
+ plugin_register_flush ("perl", perl_flush);
plugin_register_shutdown ("perl", perl_shutdown);
return 0;
} /* static int init_pi (const char **, const int) */
return (1);
}
- init_pi (perl_argc, perl_argv);
+ if (0 != init_pi (perl_argc, perl_argv))
+ return -1;
+
assert (NULL != perl_threads);
assert (NULL != perl_threads->head);