2 * collectd - src/dotnet.c
3 * Copyright (C) 2010 Florian Forster
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 * Florian Forster <ff at octo.it>
30 #include "configfile.h"
33 #include <mono/jit/jit.h>
34 #include <mono/metadata/assembly.h>
36 struct dotnet_callback_info_s
41 typedef struct dotnet_callback_info_s dotnet_callback_info_t;
43 static MonoDomain *domain = NULL;
45 static int dotnet_read (user_data_t *ud) /* {{{ */
47 dotnet_callback_info_t *ci = ud->data;
55 DEBUG ("dotnet plugin: mono_domain_get_by_id (%"PRIi32") ...",
56 (int32_t) ci->domain_id);
57 domain = mono_domain_get_by_id (ci->domain_id);
60 ERROR ("dotnet plugin: mono_domain_get_by_id failed.");
63 mono_domain_set_internal (domain);
66 DEBUG ("dotnet plugin: mono_gchandle_get_target ...");
67 object = mono_gchandle_get_target (ci->obj_handle);
70 ERROR ("dotnet plugin: mono_gchandle_get_target failed.");
74 DEBUG ("dotnet plugin: mono_object_get_class ...");
75 class = mono_object_get_class (object);
78 ERROR ("dotnet plugin: mono_object_get_class failed.");
82 DEBUG ("dotnet plugin: mono_class_get_method_from_name ...");
83 method = mono_class_get_method_from_name (class,
84 /* name = */ "read", /* nargs = */ 0);
87 ERROR ("dotnet plugin: mono_class_get_method_from_name failed.");
91 DEBUG ("dotnet plugin: mono_runtime_invoke ...");
92 ret = mono_runtime_invoke (method, object, /* params = */ NULL,
93 /* exception ptr = */ NULL);
94 DEBUG ("dotnet plugin: mono_runtime_invoke returned %p.", (void *) ret);
97 } /* }}} int dotnet_read */
99 static void dotnet_callback_info_free (void *ptr) /* {{{ */
101 dotnet_callback_info_t *ci = ptr;
106 mono_gchandle_free (ci->obj_handle);
108 } /* }}} void dotnet_callback_info_free */
110 static int dotnet_log (int severity, MonoString *message) /* {{{ */
112 char *tmp = mono_string_to_utf8 (message);
114 DEBUG ("dotnet_log (severity = %i, message = \"%s\");", severity, tmp);
117 } /* }}} int dotnet_log */
119 static int dotnet_register_read (MonoString *name, MonoObject *obj) /* {{{ */
122 dotnet_callback_info_t *ci;
127 /* Sanity checks: Make sure this object actually has the required method. */
128 class = mono_object_get_class (obj);
131 ERROR ("dotnet plugin: mono_object_get_class failed.");
135 method = mono_class_get_method_from_name (class,
136 /* name = */ "read", /* param count = */ 0);
139 ERROR ("dotnet plugin: mono_class_get_method_from_name failed.");
143 ci = malloc (sizeof (*ci));
146 ERROR ("dotnet plugin: malloc failed.");
149 memset (ci, 0, sizeof (*ci));
151 ci->domain_id = mono_domain_get_id (mono_domain_get ());
152 ci->obj_handle = mono_gchandle_new (obj, /* pinned = */ 1);
155 ud.free_func = dotnet_callback_info_free;
157 plugin_register_complex_read (/* group = */ "dotnet",
158 /* name = */ mono_string_to_utf8 (name),
159 /* callback = */ dotnet_read,
160 /* interval = */ NULL,
161 /* user data = */ &ud);
164 } /* }}} int dotnet_register_read */
166 static int dotnet_load_class (const char *assembly_name, /* {{{ */
167 const char *name_space, const char *class_name)
169 MonoAssembly *assembly;
176 domain = mono_domain_get ();
179 ERROR ("dotnet plugin: mono_domain_get failed.");
184 assembly = mono_domain_assembly_open (domain, assembly_name);
185 if (assembly == NULL)
187 ERROR ("dotnet plugin: mono_domain_assembly_open (\"%s\") failed.",
189 mono_jit_cleanup (domain);
193 image = mono_assembly_get_image (assembly);
196 ERROR ("mono_assembly_get_image failed.");
197 mono_jit_cleanup (domain);
201 class = mono_class_from_name (image,
202 (name_space != NULL) ? name_space : "",
206 ERROR ("dotnet plugin: Looking up class \"%s\" in assembly \"%s\" failed.",
207 class_name, assembly_name);
211 obj = mono_object_new (domain, class);
214 ERROR ("Creating a \"%s\" object failed.", class_name);
218 mono_runtime_object_init (obj);
220 DEBUG ("dotnet plugin: Successfully created a \"%s\" object.", class_name);
223 } /* }}} int dotnet_load_class */
227 * <LoadPlugin "Foobar">
228 * NameSpace "MyCompany"
229 * Assembly "path/to/file.dll"
237 static int dotnet_config_loadplugin (oconfig_item_t *ci) /* {{{ */
239 char *class_name = NULL;
240 char *name_space = NULL;
241 char *assembly_name = NULL;
245 status = cf_util_get_string (ci, &class_name);
248 assert (class_name != NULL);
250 for (i = 0; i < ci->children_num; i++)
252 oconfig_item_t *child = ci->children + i;
254 if (strcasecmp ("NameSpace", child->key) == 0)
255 cf_util_get_string (child, &name_space);
256 else if (strcasecmp ("Assembly", child->key) == 0)
257 cf_util_get_string (child, &assembly_name);
259 WARNING ("dotnet plugin: Config option \"%s\" is not allowed here.",
263 if (assembly_name == NULL)
265 ERROR ("dotnet plugin: No \"Assembly\" option within this \"LoadPlugin\" "
266 "block (class \"%s\").", class_name);
271 status = dotnet_load_class (assembly_name, name_space, class_name);
276 } /* }}} int dotnet_config_loadplugin */
278 static int dotnet_config (oconfig_item_t *ci) /* {{{ */
282 for (i = 0; i < ci->children_num; i++)
284 oconfig_item_t *child = ci->children + i;
286 if (strcasecmp ("LoadPlugin", child->key) == 0)
287 dotnet_config_loadplugin (child);
289 WARNING ("dotnet plugin: Ignoring unknown config option \"%s\".",
294 } /* }}} int dotnet_config */
296 void module_register (void)
298 domain = mono_jit_init (PACKAGE_NAME);
301 ERROR ("dotnet plugin: mono_jit_init failed.");
305 mono_add_internal_call ("CollectdAPI.Collectd::log", dotnet_log);
306 mono_add_internal_call ("CollectdAPI.Collectd::registerRead", dotnet_register_read);
308 plugin_register_complex_config ("dotnet", dotnet_config);
309 } /* void module_register */
311 /* vim: set sw=2 sts=2 et fdm=marker : */