diff --git a/src/perl.c b/src/perl.c
index 50def1fccb7032ffb8be01efb3f161d305f2c3d8..78e508ae4d1f1bb7c0b9ae5c9ca340b9685e79e6 100644 (file)
--- a/src/perl.c
+++ b/src/perl.c
#include "configfile.h"
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#endif
+
#include <EXTERN.h>
#include <perl.h>
static XS (Collectd_plugin_register_ds);
static XS (Collectd_plugin_unregister_ds);
static XS (Collectd_plugin_dispatch_values);
+static XS (Collectd_plugin_get_interval);
static XS (Collectd__plugin_write);
static XS (Collectd__plugin_flush);
static XS (Collectd_plugin_dispatch_notification);
sfree (data); \
} while (0)
+/*
+ * Public variable
+ */
+extern char **environ;
+
/*
* private variables
*/
{ "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_get_interval", Collectd_plugin_get_interval },
{ "Collectd::_plugin_write", Collectd__plugin_write },
{ "Collectd::_plugin_flush", Collectd__plugin_flush },
{ "Collectd::plugin_dispatch_notification",
{ "", NULL }
};
-struct {
- char name[64];
- int *var;
-} g_integers[] =
-{
- { "Collectd::interval_g", &interval_g },
- { "", NULL }
-};
-
/*
* Helper functions for data type conversion.
*/
}
if (NULL != (tmp = hv_fetch (hash, "time", 4, 0)))
- vl->time = (time_t)SvIV (*tmp);
+ {
+ double t = SvNV (*tmp);
+ vl->time = DOUBLE_TO_CDTIME_T (t);
+ }
if (NULL != (tmp = hv_fetch (hash, "interval", 8, 0)))
- vl->interval = SvIV (*tmp);
+ {
+ double t = SvNV (*tmp);
+ vl->interval = DOUBLE_TO_CDTIME_T (t);
+ }
if (NULL != (tmp = hv_fetch (hash, "host", 4, 0)))
sstrncpy (vl->host, SvPV_nolen (*tmp), sizeof (vl->host));
n->severity = NOTIF_FAILURE;
if (NULL != (tmp = hv_fetch (hash, "time", 4, 0)))
- n->time = (time_t)SvIV (*tmp);
+ {
+ double t = SvNV (*tmp);
+ n->time = DOUBLE_TO_CDTIME_T (t);
+ }
else
- n->time = time (NULL);
+ n->time = cdtime ();
if (NULL != (tmp = hv_fetch (hash, "message", 7, 0)))
sstrncpy (n->message, SvPV_nolen (*tmp), sizeof (n->message));
return -1;
if (0 != vl->time)
- if (NULL == hv_store (hash, "time", 4, newSViv (vl->time), 0))
+ {
+ double t = CDTIME_T_TO_DOUBLE (vl->time);
+ if (NULL == hv_store (hash, "time", 4, newSVnv (t), 0))
return -1;
+ }
- if (NULL == hv_store (hash, "interval", 8, newSViv (vl->interval), 0))
- return -1;
+ {
+ double t = CDTIME_T_TO_DOUBLE (vl->interval);
+ if (NULL == hv_store (hash, "interval", 8, newSVnv (t), 0))
+ return -1;
+ }
if ('\0' != vl->host[0])
if (NULL == hv_store (hash, "host", 4, newSVpv (vl->host, 0), 0))
return -1;
if (0 != n->time)
- if (NULL == hv_store (hash, "time", 4, newSViv (n->time), 0))
+ {
+ double t = CDTIME_T_TO_DOUBLE (n->time);
+ if (NULL == hv_store (hash, "time", 4, newSVnv (t), 0))
return -1;
+ }
if ('\0' != *n->message)
if (NULL == hv_store (hash, "message", 7, newSVpv (n->message, 0), 0))
XPUSHs (sv_2mortal (newRV_noinc ((SV *)notif)));
}
else if (PLUGIN_FLUSH == type) {
+ cdtime_t timeout;
+
/*
* $_[0] = $timeout;
* $_[1] = $identifier;
*/
- XPUSHs (sv_2mortal (newSViv (va_arg (ap, int))));
+ timeout = va_arg (ap, cdtime_t);
+
+ XPUSHs (sv_2mortal (newSVnv (CDTIME_T_TO_DOUBLE (timeout))));
XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
}
static XS (Collectd_plugin_dispatch_values)
{
SV *values = NULL;
- int values_idx = 0;
int ret = 0;
dXSARGS;
- if (2 == items) {
- log_warn ("Collectd::plugin_dispatch_values with two arguments "
- "is deprecated - pass the type through values->{type}.");
- values_idx = 1;
- }
- else if (1 != items) {
+ if (1 != items) {
log_err ("Usage: Collectd::plugin_dispatch_values(values)");
XSRETURN_EMPTY;
}
log_debug ("Collectd::plugin_dispatch_values: values=\"%s\"",
- SvPV_nolen (ST (values_idx)));
+ SvPV_nolen (ST (/* stack index = */ 0)));
- values = ST (values_idx);
+ values = ST (/* stack index = */ 0);
+ /* Make sure the argument is a hash reference. */
if (! (SvROK (values) && (SVt_PVHV == SvTYPE (SvRV (values))))) {
log_err ("Collectd::plugin_dispatch_values: Invalid values.");
XSRETURN_EMPTY;
}
- if (((2 == items) && (NULL == ST (0))) || (NULL == values))
- XSRETURN_EMPTY;
-
- if ((2 == items) && (NULL == hv_store ((HV *)SvRV (values), "type", 4,
- newSVsv (ST (0)), 0))) {
- log_err ("Collectd::plugin_dispatch_values: Could not store type.");
+ if (NULL == values)
XSRETURN_EMPTY;
- }
ret = pplugin_dispatch_values (aTHX_ (HV *)SvRV (values));
XSRETURN_EMPTY;
} /* static XS (Collectd_plugin_dispatch_values) */
+/*
+ * Collectd::plugin_get_interval ().
+ */
+static XS (Collectd_plugin_get_interval)
+{
+ dXSARGS;
+
+ /* make sure we don't get any unused variable warnings for 'items';
+ * don't abort, though */
+ if (items)
+ log_err ("Usage: Collectd::plugin_get_interval()");
+
+ XSRETURN_NV ((NV) CDTIME_T_TO_DOUBLE (plugin_get_interval ()));
+} /* static XS (Collectd_plugin_get_interval) */
+
/* Collectd::plugin_write (plugin, ds, vl).
*
* plugin:
aTHX = t->interp;
}
+ /* Assert that we're not running as the base thread. Otherwise, we might
+ * run into concurrency issues with c_ithread_create(). See
+ * https://github.com/collectd/collectd/issues/9 for details. */
+ assert (aTHX != perl_threads->head->interp);
+
log_debug ("perl_read: c_ithread: interp = %p (active threads: %i)",
aTHX, perl_threads->number_of_threads);
return pplugin_call_all (aTHX_ PLUGIN_READ);
static int perl_write (const data_set_t *ds, const value_list_t *vl,
user_data_t __attribute__((unused)) *user_data)
{
+ int status;
dTHX;
if (NULL == perl_threads)
aTHX = t->interp;
}
+ /* Lock the base thread if this is not called from one of the read threads
+ * to avoid race conditions with c_ithread_create(). See
+ * https://github.com/collectd/collectd/issues/9 for details. */
+ if (aTHX == perl_threads->head->interp)
+ pthread_mutex_lock (&perl_threads->mutex);
+
log_debug ("perl_write: c_ithread: interp = %p (active threads: %i)",
aTHX, perl_threads->number_of_threads);
- return pplugin_call_all (aTHX_ PLUGIN_WRITE, ds, vl);
+ status = pplugin_call_all (aTHX_ PLUGIN_WRITE, ds, vl);
+
+ if (aTHX == perl_threads->head->interp)
+ pthread_mutex_unlock (&perl_threads->mutex);
+
+ return status;
} /* static int perl_write (const data_set_t *, const value_list_t *) */
static void perl_log (int level, const char *msg,
aTHX = t->interp;
}
+ /* Lock the base thread if this is not called from one of the read threads
+ * to avoid race conditions with c_ithread_create(). See
+ * https://github.com/collectd/collectd/issues/9 for details. */
+ if (aTHX == perl_threads->head->interp)
+ pthread_mutex_lock (&perl_threads->mutex);
+
pplugin_call_all (aTHX_ PLUGIN_LOG, level, msg);
+
+ if (aTHX == perl_threads->head->interp)
+ pthread_mutex_unlock (&perl_threads->mutex);
+
return;
} /* static void perl_log (int, const char *) */
return pplugin_call_all (aTHX_ PLUGIN_NOTIF, notif);
} /* static int perl_notify (const notification_t *) */
-static int perl_flush (int timeout, const char *identifier,
+static int perl_flush (cdtime_t timeout, const char *identifier,
user_data_t __attribute__((unused)) *user_data)
{
dTHX;
return 0;
} /* static int g_pv_set (pTHX_ SV *, MAGIC *) */
-static int g_iv_get (pTHX_ SV *var, MAGIC *mg)
+static int g_interval_get (pTHX_ SV *var, MAGIC *mg)
{
- int *iv = (int *)mg->mg_ptr;
- sv_setiv (var, *iv);
+ log_warn ("Accessing $interval_g is deprecated (and might not "
+ "give the desired results) - plugin_get_interval() should "
+ "be used instead.");
+ sv_setnv (var, CDTIME_T_TO_DOUBLE (interval_g));
return 0;
-} /* static int g_iv_get (pTHX_ SV *, MAGIC *) */
+} /* static int g_interval_get (pTHX_ SV *, MAGIC *) */
-static int g_iv_set (pTHX_ SV *var, MAGIC *mg)
+static int g_interval_set (pTHX_ SV *var, MAGIC *mg)
{
- int *iv = (int *)mg->mg_ptr;
- *iv = (int)SvIV (var);
+ double nv = (double)SvNV (var);
+ log_warn ("Accessing $interval_g is deprecated (and might not "
+ "give the desired results) - plugin_get_interval() should "
+ "be used instead.");
+ interval_g = DOUBLE_TO_CDTIME_T (nv);
return 0;
-} /* static int g_iv_set (pTHX_ SV *, MAGIC *) */
+} /* static int g_interval_set (pTHX_ SV *, MAGIC *) */
static MGVTBL g_pv_vtbl = {
g_pv_get, g_pv_set, NULL, NULL, NULL, NULL, NULL
, NULL
#endif
};
-static MGVTBL g_iv_vtbl = {
- g_iv_get, g_iv_set, NULL, NULL, NULL, NULL, NULL
+static MGVTBL g_interval_vtbl = {
+ g_interval_get, g_interval_set, NULL, NULL, NULL, NULL, NULL
#if HAVE_PERL_STRUCT_MGVTBL_SVT_LOCAL
, NULL
#endif
g_strings[i].var, 0);
}
- /* global integers */
- for (i = 0; '\0' != g_integers[i].name[0]; ++i) {
- tmp = get_sv (g_integers[i].name, 1);
- sv_magicext (tmp, NULL, PERL_MAGIC_ext, &g_iv_vtbl,
- (char *)g_integers[i].var, 0);
- }
+ tmp = get_sv ("Collectd::interval_g", /* create = */ 1);
+ sv_magicext (tmp, NULL, /* how = */ PERL_MAGIC_ext,
+ /* vtbl = */ &g_interval_vtbl,
+ /* name = */ NULL, /* namelen = */ 0);
+
return;
} /* static void xs_init (pTHX) */