python-plugin-provider/python-plugin-provider.c: add logging
[babeltrace.git] / lib / plugin / plugin.c
1 /*
2 * plugin.c
3 *
4 * Babeltrace Plugin (generic)
5 *
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
8 *
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30 #define BT_LOG_TAG "PLUGIN"
31 #include <babeltrace/lib-logging-internal.h>
32
33 #include <babeltrace/babeltrace-internal.h>
34 #include <babeltrace/compiler-internal.h>
35 #include <babeltrace/ref.h>
36 #include <babeltrace/common-internal.h>
37 #include <babeltrace/plugin/plugin-internal.h>
38 #include <babeltrace/plugin/plugin-so-internal.h>
39 #include <babeltrace/graph/component-class.h>
40 #include <babeltrace/graph/component-class-internal.h>
41 #include <babeltrace/types.h>
42 #include <glib.h>
43 #include <unistd.h>
44 #include <stdlib.h>
45 #include <stdint.h>
46 #include <inttypes.h>
47 #include <sys/stat.h>
48 #include <dirent.h>
49
50 #define PYTHON_PLUGIN_PROVIDER_FILENAME "libbabeltrace-python-plugin-provider." G_MODULE_SUFFIX
51 #define PYTHON_PLUGIN_PROVIDER_SYM_NAME bt_plugin_python_create_all_from_file
52 #define PYTHON_PLUGIN_PROVIDER_SYM_NAME_STR TOSTRING(PYTHON_PLUGIN_PROVIDER_SYM_NAME)
53
54 #ifdef BT_BUILT_IN_PYTHON_PLUGIN_SUPPORT
55 #include <babeltrace/plugin/python-plugin-provider-internal.h>
56 static
57 struct bt_plugin_set *(*bt_plugin_python_create_all_from_file_sym)(const char *path) =
58 bt_plugin_python_create_all_from_file;
59 #else /* BT_BUILT_IN_PYTHON_PLUGIN_SUPPORT */
60 static GModule *python_plugin_provider_module;
61 static
62 struct bt_plugin_set *(*bt_plugin_python_create_all_from_file_sym)(const char *path);
63
64 __attribute__((constructor)) static
65 void init_python_plugin_provider(void) {
66 BT_LOGD_STR("Loading Python plugin provider module.");
67 python_plugin_provider_module =
68 g_module_open(PYTHON_PLUGIN_PROVIDER_FILENAME,
69 G_MODULE_BIND_LOCAL);
70 if (!python_plugin_provider_module) {
71 BT_LOGI("Cannot find `%s`: continuing without Python plugin support.",
72 PYTHON_PLUGIN_PROVIDER_FILENAME);
73 return;
74 }
75
76 if (!g_module_symbol(python_plugin_provider_module,
77 PYTHON_PLUGIN_PROVIDER_SYM_NAME_STR,
78 (gpointer) &bt_plugin_python_create_all_from_file_sym)) {
79 BT_LOGI("Cannot find the Python plugin provider loading symbol: continuing without Python plugin support: "
80 "file=\"%s\", symbol=\"%s\"",
81 PYTHON_PLUGIN_PROVIDER_FILENAME,
82 PYTHON_PLUGIN_PROVIDER_SYM_NAME_STR);
83 return;
84 }
85
86 BT_LOGI("Loaded Python plugin provider module: addr=%p",
87 python_plugin_provider_module);
88 }
89
90 __attribute__((destructor)) static
91 void fini_python_plugin_provider(void) {
92 if (python_plugin_provider_module) {
93 BT_LOGD("Unloading Python plugin provider module.");
94
95 if (!g_module_close(python_plugin_provider_module)) {
96 BT_LOGE("Failed to close the Python plugin provider module: %s.",
97 g_module_error());
98 }
99
100 python_plugin_provider_module = NULL;
101 }
102 }
103 #endif
104
105 extern
106 int64_t bt_plugin_set_get_plugin_count(struct bt_plugin_set *plugin_set)
107 {
108 int64_t count = -1;
109
110 if (!plugin_set) {
111 BT_LOGW_STR("Invalid parameter: plugin set is NULL.");
112 goto end;
113 }
114
115 count = (int64_t) plugin_set->plugins->len;
116
117 end:
118 return count;
119 }
120
121 extern
122 struct bt_plugin *bt_plugin_set_get_plugin(struct bt_plugin_set *plugin_set,
123 uint64_t index)
124 {
125 struct bt_plugin *plugin = NULL;
126
127 if (!plugin_set) {
128 BT_LOGW_STR("Invalid parameter: plugin set is NULL.");
129 goto end;
130 }
131
132 if (index >= plugin_set->plugins->len) {
133 BT_LOGW("Invalid parameter: index is out of bounds: "
134 "addr=%p, index=%" PRIu64 ", count=%u",
135 plugin_set, index, plugin_set->plugins->len);
136 goto end;
137 }
138
139 plugin = bt_get(g_ptr_array_index(plugin_set->plugins, index));
140
141 end:
142 return plugin;
143 }
144
145 struct bt_plugin_set *bt_plugin_create_all_from_static(void)
146 {
147 /* bt_plugin_so_create_all_from_static() logs errors */
148 return bt_plugin_so_create_all_from_static();
149 }
150
151 struct bt_plugin_set *bt_plugin_create_all_from_file(const char *path)
152 {
153 struct bt_plugin_set *plugin_set = NULL;
154
155 if (!path) {
156 BT_LOGW_STR("Invalid parameter: path is NULL.");
157 goto end;
158 }
159
160 BT_LOGD("Creating plugins from file: path=\"%s\"", path);
161
162 /* Try shared object plugins */
163 plugin_set = bt_plugin_so_create_all_from_file(path);
164 if (plugin_set) {
165 goto end;
166 }
167
168 /* Try Python plugins if support is available */
169 if (bt_plugin_python_create_all_from_file_sym) {
170 plugin_set = bt_plugin_python_create_all_from_file_sym(path);
171 if (plugin_set) {
172 goto end;
173 }
174 }
175
176 end:
177 if (plugin_set) {
178 BT_LOGD("Created %u plugins from file: "
179 "path=\"%s\", count=%u, plugin-set-addr=%p",
180 plugin_set->plugins->len, path,
181 plugin_set->plugins->len, plugin_set);
182 } else {
183 BT_LOGD("Found no plugins in file: path=\"%s\"", path);
184 }
185
186 return plugin_set;
187 }
188
189 static void destroy_gstring(void *data)
190 {
191 g_string_free(data, TRUE);
192 }
193
194 struct bt_plugin *bt_plugin_find(const char *plugin_name)
195 {
196 const char *system_plugin_dir;
197 char *home_plugin_dir = NULL;
198 const char *envvar;
199 struct bt_plugin *plugin = NULL;
200 struct bt_plugin_set *plugin_set = NULL;
201 GPtrArray *dirs = NULL;
202 int ret;
203 size_t i, j;
204
205 if (!plugin_name) {
206 BT_LOGW_STR("Invalid parameter: plugin name is NULL.");
207 goto end;
208 }
209
210 BT_LOGD("Finding named plugin in standard directories and built-in plugins: "
211 "name=\"%s\"", plugin_name);
212 dirs = g_ptr_array_new_with_free_func((GDestroyNotify) destroy_gstring);
213 if (!dirs) {
214 BT_LOGE_STR("Failed to allocate a GPtrArray.");
215 goto end;
216 }
217
218 /*
219 * Search order is:
220 *
221 * 1. BABELTRACE_PLUGIN_PATH environment variable
222 * (colon-separated list of directories)
223 * 2. ~/.local/lib/babeltrace/plugins
224 * 3. Default system directory for Babeltrace plugins, usually
225 * /usr/lib/babeltrace/plugins or
226 * /usr/local/lib/babeltrace/plugins if installed
227 * locally
228 * 4. Built-in plugins (static)
229 *
230 * Directories are searched non-recursively.
231 */
232 envvar = getenv("BABELTRACE_PLUGIN_PATH");
233 if (envvar) {
234 ret = bt_common_append_plugin_path_dirs(envvar, dirs);
235 if (ret) {
236 BT_LOGE_STR("Failed to append plugin path to array of directories.");
237 goto end;
238 }
239 }
240
241 home_plugin_dir = bt_common_get_home_plugin_path();
242 if (home_plugin_dir) {
243 GString *home_plugin_dir_str =
244 g_string_new(home_plugin_dir);
245
246 if (!home_plugin_dir_str) {
247 BT_LOGE_STR("Failed to allocate a GString.");
248 goto end;
249 }
250
251 g_ptr_array_add(dirs, home_plugin_dir_str);
252 }
253
254 system_plugin_dir = bt_common_get_system_plugin_path();
255 if (system_plugin_dir) {
256 GString *system_plugin_dir_str =
257 g_string_new(system_plugin_dir);
258
259 if (!system_plugin_dir_str) {
260 BT_LOGE_STR("Failed to allocate a GString.");
261 goto end;
262 }
263
264 g_ptr_array_add(dirs, system_plugin_dir_str);
265 }
266
267 for (i = 0; i < dirs->len; i++) {
268 GString *dir = g_ptr_array_index(dirs, i);
269
270 BT_PUT(plugin_set);
271
272 /* bt_plugin_create_all_from_dir() logs details/errors */
273 plugin_set = bt_plugin_create_all_from_dir(dir->str, BT_FALSE);
274 if (!plugin_set) {
275 BT_LOGD("No plugins found in directory: path=\"%s\"",
276 dir->str);
277 continue;
278 }
279
280 for (j = 0; j < plugin_set->plugins->len; j++) {
281 struct bt_plugin *candidate_plugin =
282 g_ptr_array_index(plugin_set->plugins, j);
283
284 if (strcmp(bt_plugin_get_name(candidate_plugin),
285 plugin_name) == 0) {
286 BT_LOGD("Plugin found in directory: name=\"%s\", path=\"%s\"",
287 plugin_name, dir->str);
288 plugin = bt_get(candidate_plugin);
289 goto end;
290 }
291 }
292
293 BT_LOGD("Plugin not found in directory: name=\"%s\", path=\"%s\"",
294 plugin_name, dir->str);
295 }
296
297 bt_put(plugin_set);
298 plugin_set = bt_plugin_create_all_from_static();
299 if (plugin_set) {
300 for (j = 0; j < plugin_set->plugins->len; j++) {
301 struct bt_plugin *candidate_plugin =
302 g_ptr_array_index(plugin_set->plugins, j);
303
304 if (strcmp(bt_plugin_get_name(candidate_plugin),
305 plugin_name) == 0) {
306 BT_LOGD("Plugin found in built-in plugins: "
307 "name=\"%s\"", plugin_name);
308 plugin = bt_get(candidate_plugin);
309 goto end;
310 }
311 }
312 }
313
314 end:
315 free(home_plugin_dir);
316 bt_put(plugin_set);
317
318 if (dirs) {
319 g_ptr_array_free(dirs, TRUE);
320 }
321
322 if (plugin) {
323 BT_LOGD("Found plugin in standard directories and built-in plugins: "
324 "addr=%p, name=\"%s\", path=\"%s\"",
325 plugin, plugin_name, bt_plugin_get_path(plugin));
326 } else {
327 BT_LOGD("No plugin found in standard directories and built-in plugins: "
328 "name=\"%s\"", plugin_name);
329 }
330
331 return plugin;
332 }
333
334 struct bt_component_class *bt_plugin_find_component_class(
335 const char *plugin_name, const char *comp_cls_name,
336 enum bt_component_class_type comp_cls_type)
337 {
338 struct bt_plugin *plugin = NULL;
339 struct bt_component_class *comp_cls = NULL;
340
341 if (!plugin_name) {
342 BT_LOGW_STR("Invalid parameter: plugin name is NULL.");
343 goto end;
344 }
345
346 if (!comp_cls_name) {
347 BT_LOGW_STR("Invalid parameter: component class name is NULL.");
348 goto end;
349 }
350
351 BT_LOGD("Finding named plugin and component class in standard directories and built-in plugins: "
352 "plugin-name=\"%s\", comp-class-name=\"%s\"",
353 plugin_name, comp_cls_name);
354 plugin = bt_plugin_find(plugin_name);
355 if (!plugin) {
356 BT_LOGD_STR("Plugin not found.");
357 goto end;
358 }
359
360 comp_cls = bt_plugin_get_component_class_by_name_and_type(
361 plugin, comp_cls_name, comp_cls_type);
362 if (!comp_cls) {
363 BT_LOGD("Component class not found in plugin: "
364 "plugin-addr=%p, plugin-path=\"%s\"",
365 plugin, bt_plugin_get_path(plugin));
366 }
367
368 end:
369 bt_put(plugin);
370 return comp_cls;
371 }
372
373 /* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */
374 static
375 struct dirent *alloc_dirent(const char *path)
376 {
377 size_t len;
378 long name_max;
379 struct dirent *entry;
380
381 name_max = pathconf(path, _PC_NAME_MAX);
382 if (name_max == -1) {
383 name_max = PATH_MAX;
384 }
385 len = offsetof(struct dirent, d_name) + name_max + 1;
386 entry = zmalloc(len);
387 return entry;
388 }
389
390 static
391 enum bt_plugin_status bt_plugin_create_append_all_from_dir(
392 struct bt_plugin_set *plugin_set, const char *path,
393 bt_bool recurse)
394 {
395 DIR *directory = NULL;
396 struct dirent *entry = NULL, *result = NULL;
397 char *file_path = NULL;
398 size_t path_len;
399 enum bt_plugin_status ret = BT_PLUGIN_STATUS_OK;
400
401 if (!path) {
402 BT_LOGW_STR("Invalid parameter: path is NULL.");
403 ret = BT_PLUGIN_STATUS_ERROR;
404 goto end;
405 }
406
407 path_len = strlen(path);
408 if (path_len >= PATH_MAX) {
409 BT_LOGW("Invalid parameter: path length is too large: "
410 "path-length=%zu", path_len);
411 ret = BT_PLUGIN_STATUS_ERROR;
412 goto end;
413 }
414
415 entry = alloc_dirent(path);
416 if (!entry) {
417 BT_LOGE_STR("Failed to allocate a directory entry.");
418 ret = BT_PLUGIN_STATUS_ERROR;
419 goto end;
420 }
421
422 file_path = zmalloc(PATH_MAX);
423 if (!file_path) {
424 BT_LOGE("Failed to allocate %zu bytes.", (size_t) PATH_MAX);
425 ret = BT_PLUGIN_STATUS_NOMEM;
426 goto end;
427 }
428
429 strncpy(file_path, path, path_len);
430 /* Append a trailing '/' to the path */
431 if (file_path[path_len - 1] != '/') {
432 file_path[path_len++] = '/';
433 }
434
435 directory = opendir(file_path);
436 if (!directory) {
437 if (errno == EACCES) {
438 BT_LOGD("Cannot open directory: %s: continuing: "
439 "path=\"%s\", errno=%d",
440 strerror(errno), file_path, errno);
441 goto end;
442 }
443
444 BT_LOGW("Cannot open directory: %s: "
445 "path=\"%s\", errno=%d",
446 strerror(errno), file_path, errno);
447 ret = BT_PLUGIN_STATUS_ERROR;
448 goto end;
449 }
450
451 /* Recursively walk directory */
452 while (!readdir_r(directory, entry, &result) && result) {
453 struct stat st;
454 int stat_ret;
455 size_t file_name_len;
456
457 if (strcmp(result->d_name, ".") == 0 ||
458 strcmp(result->d_name, "..") == 0) {
459 continue;
460 }
461
462 if (result->d_name[0] == '.') {
463 /* Skip hidden files, . and .. */
464 BT_LOGV("Skipping hidden file: path=\"%s/%s\"",
465 path, result->d_name);
466 continue;
467 }
468
469 file_name_len = strlen(result->d_name);
470
471 if (path_len + file_name_len >= PATH_MAX) {
472 BT_LOGD("Skipping file because its path length is too large: continuing: "
473 "path=\"%s/%s\", length=%zu",
474 path, result->d_name,
475 (size_t) (path_len + file_name_len));
476 continue;
477 }
478
479 strncpy(file_path + path_len, result->d_name, file_name_len);
480 file_path[path_len + file_name_len] = '\0';
481 stat_ret = stat(file_path, &st);
482 if (stat_ret < 0) {
483 /* Continue to next file / directory. */
484 BT_LOGD("Cannot get file information: %s: continuing: "
485 "path=\"%s\", errno=%d",
486 strerror(errno), file_path, errno);
487 continue;
488 }
489
490 if (S_ISDIR(st.st_mode) && recurse) {
491 ret = bt_plugin_create_append_all_from_dir(plugin_set,
492 file_path, BT_TRUE);
493 if (ret < 0) {
494 BT_LOGW("Cannot recurse into directory to find plugins: "
495 "path=\"%s\", ret=%d", file_path, ret);
496 goto end;
497 }
498 } else if (S_ISREG(st.st_mode)) {
499 struct bt_plugin_set *plugins_from_file =
500 bt_plugin_create_all_from_file(file_path);
501
502 if (plugins_from_file) {
503 size_t j;
504
505 for (j = 0; j < plugins_from_file->plugins->len; j++) {
506 struct bt_plugin *plugin =
507 g_ptr_array_index(plugins_from_file->plugins, j);
508
509 BT_LOGD("Adding plugin to plugin set: "
510 "plugin-path=\"%s\", plugin-addr=%p, plugin-name=\"%s\"",
511 file_path, plugin,
512 bt_plugin_get_name(plugin));
513 bt_plugin_set_add_plugin(plugin_set,
514 plugin);
515 }
516
517 bt_put(plugins_from_file);
518 }
519 }
520 }
521
522 end:
523 if (directory) {
524 if (closedir(directory)) {
525 /*
526 * We don't want to override the error since there is
527 * nothing could do.
528 */
529 BT_LOGE("Cannot close directory entry: %s: "
530 "path=\"%s\", errno=%d",
531 strerror(errno), path, errno);
532 }
533 }
534
535 free(entry);
536 free(file_path);
537 return ret;
538 }
539
540 struct bt_plugin_set *bt_plugin_create_all_from_dir(const char *path,
541 bt_bool recurse)
542 {
543 struct bt_plugin_set *plugin_set;
544 enum bt_plugin_status status;
545
546 BT_LOGD("Creating all plugins in directory: path=\"%s\", recurse=%d",
547 path, recurse);
548 plugin_set = bt_plugin_set_create();
549 if (!plugin_set) {
550 BT_LOGE_STR("Cannot create empty plugin set.");
551 goto error;
552 }
553
554 /* Append found plugins to array */
555 status = bt_plugin_create_append_all_from_dir(plugin_set, path,
556 recurse);
557 if (status < 0) {
558 BT_LOGW("Cannot append plugins found in directory: "
559 "path=\"%s\", status=%s",
560 path, bt_plugin_status_string(status));
561 goto error;
562 }
563
564 BT_LOGD("Created %u plugins from directory: count=%u, path=\"%s\"",
565 plugin_set->plugins->len, plugin_set->plugins->len, path);
566 goto end;
567
568 error:
569 BT_PUT(plugin_set);
570
571 end:
572 return plugin_set;
573 }
574
575 const char *bt_plugin_get_name(struct bt_plugin *plugin)
576 {
577 const char *val = NULL;
578
579 if (!plugin) {
580 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
581 goto end;
582 }
583
584 if (plugin->info.name_set) {
585 val = plugin->info.name->str;
586 }
587
588 end:
589 return val;
590 }
591
592 const char *bt_plugin_get_author(struct bt_plugin *plugin)
593 {
594 const char *val = NULL;
595
596 if (!plugin) {
597 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
598 goto end;
599 }
600
601 if (plugin->info.author_set) {
602 val = plugin->info.author->str;
603 }
604
605 end:
606 return val;
607 }
608
609 const char *bt_plugin_get_license(struct bt_plugin *plugin)
610 {
611 const char *val = NULL;
612
613 if (!plugin) {
614 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
615 goto end;
616 }
617
618 if (plugin->info.license_set) {
619 val = plugin->info.license->str;
620 }
621
622 end:
623 return val;
624 }
625
626 const char *bt_plugin_get_path(struct bt_plugin *plugin)
627 {
628 const char *val = NULL;
629
630 if (!plugin) {
631 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
632 goto end;
633 }
634
635 if (plugin->info.path_set) {
636 val = plugin->info.path->str;
637 }
638
639 end:
640 return val;
641 }
642
643 const char *bt_plugin_get_description(struct bt_plugin *plugin)
644 {
645 const char *val = NULL;
646
647 if (!plugin) {
648 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
649 goto end;
650 }
651
652 if (plugin->info.description_set) {
653 val = plugin->info.description->str;
654 }
655
656 end:
657 return val;
658 }
659
660 enum bt_plugin_status bt_plugin_get_version(struct bt_plugin *plugin,
661 unsigned int *major, unsigned int *minor, unsigned int *patch,
662 const char **extra)
663 {
664 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
665
666 if (!plugin) {
667 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
668 status = BT_PLUGIN_STATUS_ERROR;
669 goto end;
670 }
671
672 if (!plugin->info.version_set) {
673 BT_LOGV("Plugin's version is not set: addr=%p", plugin);
674 status = BT_PLUGIN_STATUS_ERROR;
675 goto end;
676 }
677
678 if (major) {
679 *major = plugin->info.version.major;
680 }
681
682 if (minor) {
683 *minor = plugin->info.version.minor;
684 }
685
686 if (patch) {
687 *patch = plugin->info.version.patch;
688 }
689
690 if (extra) {
691 *extra = plugin->info.version.extra->str;
692 }
693
694 end:
695 return status;
696 }
697
698 int64_t bt_plugin_get_component_class_count(struct bt_plugin *plugin)
699 {
700 return plugin ? plugin->comp_classes->len : (int64_t) -1;
701 }
702
703 struct bt_component_class *bt_plugin_get_component_class_by_index(
704 struct bt_plugin *plugin, uint64_t index)
705 {
706 struct bt_component_class *comp_class = NULL;
707
708 if (!plugin) {
709 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
710 goto error;
711 }
712
713 if (index >= plugin->comp_classes->len) {
714 BT_LOGW("Invalid parameter: index is out of bounds: "
715 "addr=%p, index=%" PRIu64 ", count=%u",
716 plugin, index, plugin->comp_classes->len);
717 goto error;
718 }
719
720 comp_class = g_ptr_array_index(plugin->comp_classes, index);
721 bt_get(comp_class);
722 goto end;
723
724 error:
725 BT_PUT(comp_class);
726
727 end:
728 return comp_class;
729 }
730
731 struct bt_component_class *bt_plugin_get_component_class_by_name_and_type(
732 struct bt_plugin *plugin, const char *name,
733 enum bt_component_class_type type)
734 {
735 struct bt_component_class *comp_class = NULL;
736 size_t i;
737
738 if (!plugin) {
739 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
740 goto error;
741 }
742
743 if (!name) {
744 BT_LOGW_STR("Invalid parameter: name is NULL.");
745 goto error;
746 }
747
748 for (i = 0; i < plugin->comp_classes->len; i++) {
749 struct bt_component_class *comp_class_candidate =
750 g_ptr_array_index(plugin->comp_classes, i);
751 const char *comp_class_cand_name =
752 bt_component_class_get_name(comp_class_candidate);
753 enum bt_component_class_type comp_class_cand_type =
754 bt_component_class_get_type(comp_class_candidate);
755
756 assert(comp_class_cand_name);
757 assert(comp_class_cand_type >= 0);
758
759 if (strcmp(name, comp_class_cand_name) == 0 &&
760 comp_class_cand_type == type) {
761 comp_class = bt_get(comp_class_candidate);
762 break;
763 }
764 }
765
766 goto end;
767
768 error:
769 BT_PUT(comp_class);
770
771 end:
772 return comp_class;
773 }
774
775 enum bt_plugin_status bt_plugin_add_component_class(
776 struct bt_plugin *plugin, struct bt_component_class *comp_class)
777 {
778 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
779 struct bt_component_class *comp_class_dup = NULL;
780 int comp_class_index = -1;
781
782 if (!plugin) {
783 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
784 goto error;
785 }
786
787 if (!comp_class) {
788 BT_LOGW_STR("Invalid parameter: component class is NULL.");
789 goto error;
790 }
791
792 if (plugin->frozen) {
793 BT_LOGW("Invalid parameter: plugin is frozen: "
794 "addr=%p, name=\"%s\"", plugin,
795 bt_plugin_get_name(plugin));
796 goto error;
797 }
798
799 /* Check for duplicate */
800 comp_class_dup = bt_plugin_get_component_class_by_name_and_type(plugin,
801 bt_component_class_get_name(comp_class),
802 bt_component_class_get_type(comp_class));
803 if (comp_class_dup) {
804 BT_LOGW("Invalid parameter: a component class with this name and type already exists in the plugin: "
805 "plugin-addr=%p, plugin-name=\"%s\", plugin-path=\"%s\", "
806 "comp-class-name=\"%s\", comp-class-type=%s",
807 plugin, bt_plugin_get_name(plugin),
808 bt_plugin_get_path(plugin),
809 bt_component_class_get_name(comp_class),
810 bt_component_class_type_string(
811 bt_component_class_get_type(comp_class)));
812 goto error;
813 }
814
815 /* Add new component class */
816 comp_class_index = plugin->comp_classes->len;
817 g_ptr_array_add(plugin->comp_classes, bt_get(comp_class));
818
819 /* Special case for a shared object plugin */
820 if (plugin->type == BT_PLUGIN_TYPE_SO) {
821 bt_plugin_so_on_add_component_class(plugin, comp_class);
822 }
823
824 BT_LOGD("Added component class to plugin: "
825 "plugin-addr=%p, plugin-name=\"%s\", plugin-path=\"%s\", "
826 "comp-class-addr=%p, comp-class-name=\"%s\", comp-class-type=%s",
827 plugin, bt_plugin_get_name(plugin),
828 bt_plugin_get_path(plugin),
829 comp_class,
830 bt_component_class_get_name(comp_class),
831 bt_component_class_type_string(
832 bt_component_class_get_type(comp_class)));
833 goto end;
834
835 error:
836 /* Remove entry from plugin's component classes (if added) */
837 if (comp_class_index >= 0) {
838 g_ptr_array_remove_index(plugin->comp_classes,
839 comp_class_index);
840 }
841
842 status = BT_PLUGIN_STATUS_ERROR;
843
844 end:
845 bt_put(comp_class_dup);
846 return status;
847 }
This page took 0.046966 seconds and 4 git commands to generate.