*/
#include "collectd.h"
-#include "common.h"
-#include "plugin.h"
#include "configfile.h"
#include <XSUB.h>
+/* Some versions of Perl define their own version of DEBUG... :-/ */
+#ifdef DEBUG
+# undef DEBUG
+#endif /* DEBUG */
+
+/* ... while we want the definition found in plugin.h. */
+#include "plugin.h"
+#include "common.h"
+
#define PLUGIN_INIT 0
#define PLUGIN_READ 1
#define PLUGIN_WRITE 2
static XS (Collectd_plugin_register);
static XS (Collectd_plugin_unregister);
static XS (Collectd_plugin_dispatch_values);
+static XS (Collectd_plugin_log);
/*
{
"LoadPlugin",
"BaseName",
- NULL
+ "IncludeDir"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static PerlInterpreter *perl = NULL;
-static char base_name[DATA_MAX_NAME_LEN] = "Collectd::Plugin";
+static char base_name[DATA_MAX_NAME_LEN] = "";
static char *plugin_types[] = { "init", "read", "write", "shutdown" };
static HV *plugins[PLUGIN_TYPES];
{ "Collectd::plugin_register", Collectd_plugin_register },
{ "Collectd::plugin_unregister", Collectd_plugin_unregister },
{ "Collectd::plugin_dispatch_values", Collectd_plugin_dispatch_values },
+ { "Collectd::plugin_log", Collectd_plugin_log },
{ "", NULL }
};
* Internal functions.
*/
+static char *get_module_name (char *buf, size_t buf_len, const char *module) {
+ int status = 0;
+ if (base_name[0] == '\0')
+ status = snprintf (buf, buf_len, "%s", module);
+ else
+ status = snprintf (buf, buf_len, "%s::%s", base_name, module);
+ if ((status < 0) || (status >= buf_len))
+ return (NULL);
+ buf[buf_len] = '\0';
+ return (buf);
+} /* char *get_module_name */
+
/*
* Add a new plugin with the given name.
*/
if (p->wait_time > 86400)
p->wait_time = 86400;
- log_warn ("%s::%s->read() failed. Will suspend it for %i seconds.",
- base_name, plugin, p->wait_left);
+ log_warn ("%s->read() failed. Will suspend it for %i seconds.",
+ plugin, p->wait_left);
}
else if (PLUGIN_INIT == type) {
int i = 0;
- log_err ("%s::%s->init() failed. Plugin will be disabled.",
- base_name, plugin, status);
+ log_err ("%s->init() failed. Plugin will be disabled.",
+ plugin, status);
for (i = 0; i < PLUGIN_TYPES; ++i)
pplugin_unregister (i, plugin);
}
else if (PLUGIN_LOG != type) {
- log_warn ("%s::%s->%s() failed with status %i.",
- base_name, plugin, plugin_types[type], status);
+ log_warn ("%s->%s() failed with status %i.",
+ plugin, plugin_types[type], status);
}
va_end (ap);
dXSARGS;
- items = 2;
if (2 != items) {
log_err ("Usage: Collectd::plugin_dispatch_values(name, values)");
XSRETURN_EMPTY;
} /* static XS (Collectd_plugin_dispatch_values) */
/*
+ * Collectd::plugin_log (level, message).
+ *
+ * level:
+ * log level (LOG_DEBUG, ... LOG_ERR)
+ *
+ * message:
+ * log message
+ */
+static XS (Collectd_plugin_log)
+{
+ dXSARGS;
+
+ if (2 != items) {
+ log_err ("Usage: Collectd::plugin_log(level, message)");
+ XSRETURN_EMPTY;
+ }
+
+ log_debug ("Collectd::plugin_log: level = %i, message = \"%s\"",
+ SvIV (ST (0)), SvPV_nolen (ST (1)));
+ plugin_log (SvIV (ST (0)), SvPV_nolen (ST (1)));
+ XSRETURN_YES;
+} /* static XS (Collectd_plugin_log) */
+
+/*
* Collectd::bootstrap ().
*/
static XS (boot_Collectd)
static int perl_config (const char *key, const char *value)
{
+ assert (NULL != perl);
+
log_debug ("perl_config: key = \"%s\", value=\"%s\"", key, value);
if (0 == strcasecmp (key, "LoadPlugin")) {
- log_debug ("perl_config: loading perl plugin \"%s\"", value);
+ char module_name[DATA_MAX_NAME_LEN];
+ if (get_module_name (module_name, sizeof (module_name), value)
+ == NULL) {
+ log_err ("Invalid module name %s", value);
+ return (1);
+ } /* if (get_module_name == NULL) */
+
+ log_debug ("perl_config: loading perl plugin \"%s\"", value);
Perl_load_module (perl, PERL_LOADMOD_NOIMPORT,
- Perl_newSVpvf (perl, "%s::%s", base_name, value),
+ Perl_newSVpv (perl, module_name, strlen (module_name)),
Nullsv);
}
else if (0 == strcasecmp (key, "BaseName")) {
log_debug ("perl_config: Setting plugin basename to \"%s\"", value);
- strncpy (base_name, value, DATA_MAX_NAME_LEN);
- base_name[DATA_MAX_NAME_LEN - 1] = '\0';
+ strncpy (base_name, value, sizeof (base_name));
+ base_name[sizeof (base_name) - 1] = '\0';
+ }
+ else if (0 == strcasecmp (key, "IncludeDir")) {
+ Perl_av_unshift (perl, GvAVn (PL_incgv), 1);
+ Perl_av_store (perl, GvAVn (PL_incgv),
+ 0, Perl_newSVpv (perl, value, strlen (value)));
}
else {
return -1;
static int perl_init (void)
{
+ assert (NULL != perl);
+
PERL_SET_CONTEXT (perl);
return pplugin_call_all (PLUGIN_INIT);
} /* static int perl_init (void) */
static int perl_read (void)
{
+ assert (NULL != perl);
+
PERL_SET_CONTEXT (perl);
return pplugin_call_all (PLUGIN_READ);
} /* static int perl_read (void) */
static int perl_write (const data_set_t *ds, const value_list_t *vl)
{
+ assert (NULL != perl);
+
PERL_SET_CONTEXT (perl);
return pplugin_call_all (PLUGIN_WRITE, ds, vl);
} /* static int perl_write (const data_set_t *, const value_list_t *) */
static void perl_log (int level, const char *msg)
{
+ assert (NULL != perl);
+
PERL_SET_CONTEXT (perl);
pplugin_call_all (PLUGIN_LOG, level, msg);
return;
int i = 0;
int ret = 0;
+ plugin_unregister_log ("perl");
+ plugin_unregister_config ("perl");
+ plugin_unregister_init ("perl");
+ plugin_unregister_read ("perl");
+ plugin_unregister_write ("perl");
+
+ assert (NULL != perl);
+
PERL_SET_CONTEXT (perl);
ret = pplugin_call_all (PLUGIN_SHUTDOWN);
perl_destruct (perl);
perl_free (perl);
+ perl = NULL;
PERL_SYS_TERM ();
+
+ plugin_unregister_shutdown ("perl");
return ret;
} /* static void perl_shutdown (void) */
plugin_register_log ("perl", perl_log);
plugin_register_config ("perl", perl_config, config_keys, config_keys_num);
plugin_register_init ("perl", perl_init);
+
plugin_register_read ("perl", perl_read);
+
plugin_register_write ("perl", perl_write);
plugin_register_shutdown ("perl", perl_shutdown);
return;