+static void _plugin_register_generic_userdata(pTHX, int type,
+ const char *desc) {
+ int ret = 0;
+ user_data_t userdata;
+ char *pluginname;
+
+ dXSARGS;
+
+ if (2 != items) {
+ log_err("Usage: Collectd::plugin_register_%s(pluginname, subname)", desc);
+ XSRETURN_EMPTY;
+ }
+
+ if (!SvOK(ST(0))) {
+ log_err("Collectd::plugin_register_%s(pluginname, subname): "
+ "Invalid pluginname",
+ desc);
+ XSRETURN_EMPTY;
+ }
+ if (!SvOK(ST(1))) {
+ log_err("Collectd::plugin_register_%s(pluginname, subname): "
+ "Invalid subname",
+ desc);
+ XSRETURN_EMPTY;
+ }
+
+ /* Use pluginname as-is to allow flush a single perl plugin */
+ pluginname = SvPV_nolen(ST(0));
+
+ log_debug("Collectd::plugin_register_%s: "
+ "plugin = \"%s\", sub = \"%s\"",
+ desc, pluginname, SvPV_nolen(ST(1)));
+
+ memset(&userdata, 0, sizeof(userdata));
+ userdata.data = strdup(SvPV_nolen(ST(1)));
+ userdata.free_func = free;
+
+ if (PLUGIN_READ == type) {
+ ret = plugin_register_complex_read(
+ "perl", /* group */
+ pluginname, perl_read, plugin_get_interval(), /* Default interval */
+ &userdata);
+ } else if (PLUGIN_WRITE == type) {
+ ret = plugin_register_write(pluginname, perl_write, &userdata);
+ } else if (PLUGIN_LOG == type) {
+ ret = plugin_register_log(pluginname, perl_log, &userdata);
+ } else if (PLUGIN_NOTIF == type) {
+ ret = plugin_register_notification(pluginname, perl_notify, &userdata);
+ } else if (PLUGIN_FLUSH == type) {
+ if (1 == register_legacy_flush) { /* For collectd-5.7 only, #1731 */
+ register_legacy_flush = 0;
+ ret = plugin_register_flush("perl", perl_flush, /* user_data = */ NULL);
+ }
+
+ if (0 == ret) {
+ ret = plugin_register_flush(pluginname, perl_flush, &userdata);
+ } else {
+ free(userdata.data);
+ }
+ } else {
+ ret = -1;
+ }
+
+ if (0 == ret)
+ XSRETURN_YES;
+ else
+ XSRETURN_EMPTY;
+} /* static void _plugin_register_generic_userdata ( ... ) */
+
+/*
+ * Collectd::plugin_register_TYPE (pluginname, subname).
+ *
+ * pluginname:
+ * name of the perl plugin
+ *
+ * subname:
+ * name of the plugin's subroutine that does the work
+ */
+
+static XS(Collectd_plugin_register_read) {
+ return _plugin_register_generic_userdata(aTHX, PLUGIN_READ, "read");
+}
+
+static XS(Collectd_plugin_register_write) {
+ return _plugin_register_generic_userdata(aTHX, PLUGIN_WRITE, "write");
+}
+
+static XS(Collectd_plugin_register_log) {
+ return _plugin_register_generic_userdata(aTHX, PLUGIN_LOG, "log");
+}
+
+static XS(Collectd_plugin_register_notification) {
+ return _plugin_register_generic_userdata(aTHX, PLUGIN_NOTIF, "notification");
+}
+
+static XS(Collectd_plugin_register_flush) {
+ return _plugin_register_generic_userdata(aTHX, PLUGIN_FLUSH, "flush");
+}
+
+typedef int perl_unregister_function_t(const char *name);
+
+static void _plugin_unregister_generic(pTHX, perl_unregister_function_t *unreg,
+ const char *desc) {
+ dXSARGS;
+
+ if (1 != items) {
+ log_err("Usage: Collectd::plugin_unregister_%s(pluginname)", desc);
+ XSRETURN_EMPTY;
+ }
+
+ if (!SvOK(ST(0))) {
+ log_err("Collectd::plugin_unregister_%s(pluginname): "
+ "Invalid pluginname",
+ desc);
+ XSRETURN_EMPTY;
+ }
+
+ log_debug("Collectd::plugin_unregister_%s: plugin = \"%s\"", desc,
+ SvPV_nolen(ST(0)));
+
+ unreg(SvPV_nolen(ST(0)));
+
+ XSRETURN_EMPTY;
+
+ return;
+} /* static void _plugin_unregister_generic ( ... ) */
+
+/*
+ * Collectd::plugin_unregister_TYPE (pluginname).
+ *
+ * TYPE:
+ * type of callback to be unregistered: read, write, log, notification, flush
+ *
+ * pluginname:
+ * name of the perl plugin
+ */
+
+static XS(Collectd_plugin_unregister_read) {
+ return _plugin_unregister_generic(aTHX, plugin_unregister_read, "read");
+}
+
+static XS(Collectd_plugin_unregister_write) {
+ return _plugin_unregister_generic(aTHX, plugin_unregister_write, "write");
+}
+
+static XS(Collectd_plugin_unregister_log) {
+ return _plugin_unregister_generic(aTHX, plugin_unregister_log, "log");
+}
+
+static XS(Collectd_plugin_unregister_notification) {
+ return _plugin_unregister_generic(aTHX, plugin_unregister_notification,
+ "notification");
+}
+
+static XS(Collectd_plugin_unregister_flush) {
+ return _plugin_unregister_generic(aTHX, plugin_unregister_flush, "flush");
+}
+