};
typedef struct dotnet_callback_info_s dotnet_callback_info_t;
-static MonoDomain *domain = NULL;
+static MonoDomain *_domain = NULL;
static int dotnet_read (user_data_t *ud) /* {{{ */
{
dotnet_callback_info_t *ci = ud->data;
+ MonoDomain *domain;
+ MonoThread *thread;
MonoClass *class;
MonoObject *object;
MonoMethod *method;
MonoObject *ret;
- MonoThread *thread;
-
- thread = mono_thread_attach (domain);
-#if 0
- MonoDomain *domain;
DEBUG ("dotnet plugin: mono_domain_get_by_id (%"PRIi32") ...",
(int32_t) ci->domain_id);
domain = mono_domain_get_by_id (ci->domain_id);
ERROR ("dotnet plugin: mono_domain_get_by_id failed.");
return (-1);
}
- mono_domain_set_internal (domain);
-#endif
+
+ thread = mono_thread_attach (domain);
+ if (thread == NULL)
+ {
+ ERROR ("dotnet plugin: mono_thread_attach failed.");
+ return (-1);
+ }
+
+ if (!mono_domain_set (domain, /* force = */ 0))
+ {
+ ERROR ("dotnet plugin: mono_domain_set failed.");
+ return (-1);
+ }
DEBUG ("dotnet plugin: mono_gchandle_get_target ...");
object = mono_gchandle_get_target (ci->obj_handle);
sfree (ci);
} /* }}} void dotnet_callback_info_free */
+static MonoMethod *dotnet_object_method_get_from_name (MonoObject *object, /* {{{ */
+ const char *name, int param_count)
+{
+ MonoClass *class;
+
+ class = mono_object_get_class (object);
+ if (class == NULL)
+ return (NULL);
+
+ while (42)
+ {
+ MonoClass *pclass;
+ MonoMethod *method;
+
+ method = mono_class_get_method_from_name (class, name, param_count);
+ if (method != NULL)
+ return (method);
+
+ pclass = mono_class_get_parent (class);
+ if ((pclass == NULL) || (pclass == class))
+ {
+ ERROR ("dotnet plugin: Unable to find method \"%s\" in class \"%s\".",
+ name, mono_class_get_name (mono_object_get_class (object)));
+ return (NULL);
+ }
+ class = pclass;
+ } /* while (42) */
+ /* Not reached */
+ return (NULL);
+} /* }}} MonoMethod *dotnet_object_method_get_from_name */
+
+static MonoProperty *dotnet_object_get_property_from_name (MonoObject *object, /* {{{ */
+ const char *name)
+{
+ MonoClass *class;
+
+ class = mono_object_get_class (object);
+
+ while (42)
+ {
+ MonoClass *pclass;
+ MonoProperty *prop;
+
+ prop = mono_class_get_property_from_name (class, name);
+ if (prop != NULL)
+ return (prop);
+
+ pclass = mono_class_get_parent (class);
+ if ((pclass == NULL) || (pclass == class))
+ {
+ ERROR ("dotnet plugin: Unable to find property \"%s\" in class \"%s\".",
+ name, mono_class_get_name (mono_object_get_class (object)));
+ return (NULL);
+ }
+ class = pclass;
+ } /* while (42) */
+ /* Not reached */
+ return (NULL);
+} /* }}} MonoProperty *dotnet_object_get_property_from_name */
+
+static int dotnet_object_method_get_string (MonoObject *obj, /* {{{ */
+ const char *method_name, char *buffer, size_t buffer_size)
+{
+ MonoMethod *method;
+ MonoObject *ret;
+ char *tmp;
+
+ method = dotnet_object_method_get_from_name (obj, method_name, /* nargs = */ 0);
+ if (method == NULL)
+ return (-1);
+
+ ret = mono_runtime_invoke (method, obj, /* params = */ NULL, /* exception = */ NULL);
+ if (ret == NULL)
+ return (-2);
+
+ tmp = mono_string_to_utf8 ((MonoString *) ret);
+ if (tmp == NULL)
+ {
+ ERROR ("dotnet plugin: mono_string_to_utf8 failed.");
+ return (-3);
+ }
+ DEBUG ("dotnet plugin: Method \"%s\" returned string \"%s\".",
+ mono_method_get_name (method), tmp);
+
+ sstrncpy (buffer, tmp, buffer_size);
+ return (0);
+} /* }}} int dotnet_object_method_get_string */
+
+static int dotnet_object_method_get_cdtime (MonoObject *obj, /* {{{ */
+ const char *method_name, cdtime_t *ret_value)
+{
+ MonoMethod *method;
+ MonoObject *ret_obj;
+ double tmp;
+
+ method = dotnet_object_method_get_from_name (obj, method_name, /* nargs = */ 0);
+ if (method == NULL)
+ return (-1);
+
+ ret_obj = mono_runtime_invoke (method, obj, /* params = */ NULL, /* exception = */ NULL);
+ if (ret_obj == NULL)
+ return (-2);
+
+ tmp = *((double *) mono_object_unbox (ret_obj));
+ DEBUG ("dotnet plugin: Method \"%s\" returned value %.3f.",
+ mono_method_get_name (method), tmp);
+ *ret_value = DOUBLE_TO_CDTIME_T (tmp);
+
+ return (0);
+} /* }}} int dotnet_object_method_get_cdtime */
+
+static int dotnet_object_method_get_values (MonoObject *obj, /* {{{ */
+ value_list_t *vl)
+{
+ MonoMethod *method;
+ MonoObject *ilist_obj;
+ MonoObject *tmp_obj;
+ MonoProperty *count_prop;
+ MonoProperty *item_prop;
+ int32_t i;
+
+ method = dotnet_object_method_get_from_name (obj, "getValues", /* nargs = */ 0);
+ if (method == NULL)
+ return (-1);
+
+ ilist_obj = mono_runtime_invoke (method, obj, /* params = */ NULL, /* exception = */ NULL);
+ if (ilist_obj == NULL)
+ return (-2);
+
+ count_prop = dotnet_object_get_property_from_name (ilist_obj, "Count");
+ if (count_prop == NULL)
+ {
+ ERROR ("dotnet plugin: dotnet_object_get_property_from_name (\"Count\") failed.");
+ return (-4);
+ }
+
+ item_prop = dotnet_object_get_property_from_name (ilist_obj, "Item");
+ if (item_prop == NULL)
+ {
+ ERROR ("dotnet plugin: dotnet_object_get_property_from_name (\"Item\") failed.");
+ return (-5);
+ }
+
+ method = mono_property_get_get_method (count_prop);
+ tmp_obj = mono_runtime_invoke (method, ilist_obj, /* params = */ NULL, /* exception = */ NULL);
+ if (tmp_obj == NULL)
+ {
+ ERROR ("dotnet plugin: mono_runtime_invoke failed.");
+ return (-6);
+ }
+ DEBUG ("dotnet plugin: Type of the Count property is \"%s\".",
+ mono_class_get_name (mono_object_get_class (tmp_obj)));
+
+ vl->values_len = (int) *((int32_t *) mono_object_unbox (tmp_obj));
+ DEBUG ("dotnet plugin: vl->values_len = %i;", vl->values_len);
+
+ if (vl->values_len <= 0)
+ {
+ vl->values_len = 0;
+ return (-7);
+ }
+
+ vl->values = calloc ((size_t) vl->values_len, sizeof (*vl->values));
+ if (vl->values == NULL)
+ {
+ vl->values_len = 0;
+ return (-8);
+ }
+
+ for (i = 0; i < ((int32_t) vl->values_len); i++)
+ {
+ void *args[2] = { &i, NULL };
+ MonoObject *value_obj;
+ const char *class_name;
+
+ method = mono_property_get_get_method (item_prop);
+ value_obj = mono_runtime_invoke (method, ilist_obj, /* params = */ args, /* exception = */ NULL);
+ if (value_obj == NULL)
+ {
+ ERROR ("dotnet plugin: Item(%i) failed.", i);
+ return (-7);
+ }
+
+ class_name = mono_class_get_name (mono_object_get_class (value_obj));
+ if (strcmp ("gaugeValue", class_name) == 0)
+ {
+ MonoObject *gauge_obj;
+
+ method = dotnet_object_method_get_from_name (value_obj, "toDouble", /* nargs = */ 0);
+ if (method == NULL)
+ return (-9);
+
+ gauge_obj = mono_runtime_invoke (method, value_obj, /* args = */ NULL, /* exception = */ NULL);
+ if (gauge_obj == NULL)
+ return (-10);
+
+ vl->values[i].gauge = (gauge_t) *((double *) mono_object_unbox (gauge_obj));
+ DEBUG ("dotnet plugin: Gauge value %"PRIi32" = %g;",
+ i, vl->values[i].gauge);
+ }
+ else if (strcmp ("deriveValue", class_name) == 0)
+ {
+ MonoObject *derive_obj;
+
+ method = dotnet_object_method_get_from_name (value_obj, "toLong", /* nargs = */ 0);
+ if (method == NULL)
+ return (-9);
+
+ derive_obj = mono_runtime_invoke (method, value_obj, /* args = */ NULL, /* exception = */ NULL);
+ if (derive_obj == NULL)
+ return (-10);
+
+ vl->values[i].derive = (derive_t) *((int64_t *) mono_object_unbox (derive_obj));
+ DEBUG ("dotnet plugin: Derive value %"PRIi32" = %"PRIi64";",
+ i, vl->values[i].derive);
+ }
+ }
+
+ return (0);
+} /* }}} int dotnet_object_method_get_values */
+
+/*
+ * Functions exposed to .Net
+ */
static int dotnet_log (int severity, MonoString *message) /* {{{ */
{
char *tmp = mono_string_to_utf8 (message);
return (0);
} /* }}} int dotnet_register_read */
+static int dotnet_dispatch_values (MonoObject *obj) /* {{{ */
+{
+ value_list_t vl = VALUE_LIST_INIT;
+ int status;
+
+ status = dotnet_object_method_get_string (obj, "getHost", vl.host, sizeof (vl.host));
+ if (status != 0)
+ return (status);
+
+ status = dotnet_object_method_get_string (obj, "getPlugin", vl.plugin, sizeof (vl.plugin));
+ if (status != 0)
+ return (status);
+
+ status = dotnet_object_method_get_string (obj, "getPluginInstance", vl.plugin_instance, sizeof (vl.plugin_instance));
+ if (status != 0)
+ return (status);
+
+ status = dotnet_object_method_get_string (obj, "getType", vl.type, sizeof (vl.type));
+ if (status != 0)
+ return (status);
+
+ status = dotnet_object_method_get_string (obj, "getTypeInstance", vl.type_instance, sizeof (vl.type_instance));
+ if (status != 0)
+ return (status);
+
+ status = dotnet_object_method_get_cdtime (obj, "getInterval", &vl.interval);
+ if (status != 0)
+ return (status);
+
+ status = dotnet_object_method_get_cdtime (obj, "getTime", &vl.time);
+ if (status != 0)
+ return (status);
+
+ status = dotnet_object_method_get_values (obj, &vl);
+ if (status != 0)
+ return (status);
+
+ status = plugin_dispatch_values (&vl);
+ sfree (vl.values);
+
+ return (status);
+} /* }}} int dotnet_dispatch_values */
+
+/*
+ * Initialization functions
+ */
static int dotnet_load_class (const char *assembly_name, /* {{{ */
const char *name_space, const char *class_name)
{
+ MonoDomain *domain;
+ MonoThread *thread;
MonoAssembly *assembly;
MonoImage *image;
MonoClass *class;
MonoObject *obj;
-#if 0
- MonoDomain *domain;
- domain = mono_domain_get ();
+ domain = mono_domain_create ();
if (domain == NULL)
{
- ERROR ("dotnet plugin: mono_domain_get failed.");
+ ERROR ("dotnet plugin: mono_domain_create failed.");
+ return (-1);
+ }
+
+ thread = mono_thread_attach (domain);
+ if (thread == NULL)
+ {
+ ERROR ("dotnet plugin: mono_thread_attach failed.");
+ mono_domain_free (domain, /* force = */ 0);
+ return (-1);
+ }
+
+ if (!mono_domain_set (domain, /* force = */ 0))
+ {
+ ERROR ("dotnet plugin: mono_domain_set failed.");
+ mono_thread_detach (thread);
+ mono_domain_free (domain, /* force = */ 0);
return (-1);
}
-#endif
assembly = mono_domain_assembly_open (domain, assembly_name);
if (assembly == NULL)
{
ERROR ("dotnet plugin: mono_domain_assembly_open (\"%s\") failed.",
assembly_name);
- mono_jit_cleanup (domain);
+ mono_thread_detach (thread);
+ mono_domain_free (domain, /* force = */ 0);
return (-1);
}
image = mono_assembly_get_image (assembly);
if (image == NULL)
{
- ERROR ("mono_assembly_get_image failed.");
- mono_jit_cleanup (domain);
+ ERROR ("dotnet plugin: mono_assembly_get_image failed.");
+ mono_thread_detach (thread);
+ mono_domain_free (domain, /* force = */ 0);
return (-1);
}
{
ERROR ("dotnet plugin: Looking up class \"%s\" in assembly \"%s\" failed.",
class_name, assembly_name);
+ mono_thread_detach (thread);
+ mono_domain_free (domain, /* force = */ 0);
return (-1);
}
obj = mono_object_new (domain, class);
if (obj == NULL)
{
- ERROR ("Creating a \"%s\" object failed.", class_name);
+ ERROR ("dotnet plugin: Creating a \"%s\" object failed.", class_name);
+ mono_thread_detach (thread);
+ mono_domain_free (domain, /* force = */ 0);
return (-1);
}
DEBUG ("dotnet plugin: Successfully created a \"%s\" object.", class_name);
+ mono_thread_detach (thread);
return (0);
} /* }}} int dotnet_load_class */
void module_register (void)
{
- domain = mono_jit_init (PACKAGE_NAME);
- if (domain == NULL)
+ _domain = mono_jit_init (PACKAGE_NAME);
+ if (_domain == NULL)
{
ERROR ("dotnet plugin: mono_jit_init failed.");
return;
mono_add_internal_call ("CollectdAPI.Collectd::log", dotnet_log);
mono_add_internal_call ("CollectdAPI.Collectd::registerRead", dotnet_register_read);
+ mono_add_internal_call ("CollectdAPI.Collectd::dispatchValues", dotnet_dispatch_values);
plugin_register_complex_config ("dotnet", dotnet_config);
} /* void module_register */