2 * Copyright (c) 2012, Intel Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Intel Corporation nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <murphy/common/macros.h>
33 #include <murphy/common/log.h>
34 #include <murphy/common/debug.h>
35 #include <murphy/common/mm.h>
36 #include <murphy/common/list.h>
37 #include <murphy/common/hashtbl.h>
38 #include <murphy/common/utils.h>
39 #include <murphy/core/plugin.h>
40 #include <murphy/core/method.h>
44 char *name; /* name of methods in this chain */
45 mrp_list_hook_t methods; /* list of exported methods */
50 __MRP_METHOD_FIELDS(); /* method fields */
51 mrp_list_hook_t hook; /* to method table */
55 static void purge_method_list(void *key, void *object);
58 static mrp_htbl_t *methods = NULL; /* hash table of method lists */
61 static int create_method_table(void)
63 mrp_htbl_config_t hcfg;
66 hcfg.comp = mrp_string_comp;
67 hcfg.hash = mrp_string_hash;
68 hcfg.free = purge_method_list;
70 methods = mrp_htbl_create(&hcfg);
79 MRP_EXIT static void destroy_method_table(void)
81 mrp_htbl_destroy(methods, TRUE);
86 static void free_method(method_t *m)
90 mrp_free(m->signature);
96 static method_t *alloc_method(mrp_method_descr_t *method)
100 m = mrp_allocz(sizeof(*m));
103 mrp_list_init(&m->hook);
104 m->name = mrp_strdup(method->name);
105 m->signature = mrp_strdup(method->signature);
107 if (m->name != NULL &&
108 (m->signature != NULL || method->signature == NULL)) {
109 m->native_ptr = method->native_ptr;
110 m->script_ptr = method->script_ptr;
111 m->plugin = method->plugin;
123 static method_list_t *create_method_list(const char *name)
127 if (MRP_UNLIKELY(methods == NULL)) {
128 if (create_method_table() < 0)
132 l = mrp_allocz(sizeof(*l));
135 mrp_list_init(&l->methods);
136 l->name = mrp_strdup(name);
138 if (l->name != NULL) {
139 if (mrp_htbl_insert(methods, (void *)l->name, (void *)l))
151 static void free_method_list(method_list_t *l)
153 mrp_list_hook_t *p, *n;
157 mrp_list_foreach(&l->methods, p, n) {
158 m = mrp_list_entry(p, typeof(*m), hook);
160 mrp_list_delete(&m->hook);
170 static void purge_method_list(void *key, void *object)
174 free_method_list(object);
178 static method_list_t *lookup_method_list(const char *name)
183 l = mrp_htbl_lookup(methods, (void *)name);
191 static inline int check_signatures(const char *sig1, const char *sig2)
193 static int warned = FALSE;
199 mrp_log_warning("XXX TODO: implement signature checking (%s@%s:%d)",
200 __FUNCTION__, __FILE__, __LINE__);
208 static method_t *lookup_method(const char *name, const char *signature,
210 int (*script_ptr)(mrp_plugin_t *plugin,
212 mrp_script_env_t *env),
213 mrp_plugin_t *plugin)
217 mrp_list_hook_t *p, *n;
219 l = lookup_method_list(name);
222 mrp_list_foreach(&l->methods, p, n) {
223 m = mrp_list_entry(p, typeof(*m), hook);
225 if (((m->signature == NULL && signature == NULL) ||
226 (m->signature != NULL && signature != NULL &&
227 !strcmp(m->signature, signature))) &&
228 m->native_ptr == native_ptr && m->script_ptr == script_ptr &&
238 method_t *find_method(const char *name, const char *signature)
242 mrp_list_hook_t *p, *n;
246 base = strrchr(name, '.');
256 l = lookup_method_list(base);
259 mrp_list_foreach(&l->methods, p, n) {
260 m = mrp_list_entry(p, typeof(*m), hook);
262 if (signature != NULL && m->signature != NULL)
263 if (!check_signatures(signature, m->signature))
267 if (m->plugin == NULL)
269 if (strncmp(name, m->plugin->instance, plen) ||
270 m->plugin->instance[plen] != '\0')
283 static int export_method(method_t *method)
287 l = lookup_method_list(method->name);
290 l = create_method_list(method->name);
296 mrp_ref_plugin(method->plugin);
297 mrp_list_append(&l->methods, &method->hook);
303 static int remove_method(const char *name, const char *signature,
305 int (*script_ptr)(mrp_plugin_t *plugin,
307 mrp_script_env_t *env),
308 mrp_plugin_t *plugin)
312 m = lookup_method(name, signature, native_ptr, script_ptr, plugin);
315 mrp_list_delete(&m->hook);
316 mrp_unref_plugin(m->plugin);
328 int mrp_export_method(mrp_method_descr_t *method)
332 if (lookup_method(method->name, method->signature,
333 method->native_ptr, method->script_ptr,
334 method->plugin) != NULL)
337 m = alloc_method(method);
340 if (export_method(m) == 0) {
341 mrp_log_info("exported method %s (%s) %s%s.",
343 method->signature ? method->signature : "-",
344 method->plugin ? "from plugin " : "",
345 method->plugin ? method->plugin->instance : "");
353 mrp_log_error("Failed to export method %s (%s) %s%s.",
354 method->name, method->signature,
355 method->plugin ? "from plugin " : "",
356 method->plugin ? method->plugin->instance : "");
362 int mrp_remove_method(mrp_method_descr_t *method)
364 return remove_method(method->name, method->signature,
365 method->native_ptr, method->script_ptr,
370 int mrp_import_method(const char *name, const char *signature,
372 int (**script_ptr)(mrp_plugin_t *plugin, const char *name,
373 mrp_script_env_t *env),
374 mrp_plugin_t **plugin)
378 if ((script_ptr != NULL && plugin == NULL) ||
379 (script_ptr == NULL && plugin != NULL)) {
384 m = find_method(name, signature);
391 if ((native_ptr != NULL && m->native_ptr == NULL) ||
392 (script_ptr != NULL && m->script_ptr == NULL)) {
397 mrp_ref_plugin(m->plugin);
399 if (native_ptr != NULL)
400 *native_ptr = m->native_ptr;
401 if (script_ptr != NULL) {
402 *script_ptr = m->script_ptr;
410 int mrp_release_method(const char *name, const char *signature,
412 int (**script_ptr)(mrp_plugin_t *plugin,
414 mrp_script_env_t *env))
418 m = find_method(name, signature);
425 if ((native_ptr != NULL && (*native_ptr != m->native_ptr)) ||
426 (script_ptr != NULL && (*script_ptr != m->script_ptr))) {
431 mrp_unref_plugin(m->plugin);
433 if (native_ptr != NULL)
435 if (script_ptr != NULL)