Fix: make Python plugin provider have its own log level
[babeltrace.git] / lib / plugin / plugin.c
CommitLineData
33b34c43
PP
1/*
2 * plugin.c
3 *
55bb57e0 4 * Babeltrace Plugin (generic)
33b34c43
PP
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
8c1a3187
PP
30#define BT_LOG_TAG "PLUGIN"
31#include <babeltrace/lib-logging-internal.h>
32
6fbd4105 33#include <babeltrace/babeltrace-internal.h>
3d9990ac 34#include <babeltrace/compiler-internal.h>
33b34c43 35#include <babeltrace/ref.h>
1670bffd 36#include <babeltrace/common-internal.h>
33b34c43 37#include <babeltrace/plugin/plugin-internal.h>
55bb57e0 38#include <babeltrace/plugin/plugin-so-internal.h>
8c1a3187
PP
39#include <babeltrace/graph/component-class.h>
40#include <babeltrace/graph/component-class-internal.h>
c55a9f58 41#include <babeltrace/types.h>
33b34c43 42#include <glib.h>
33b34c43
PP
43#include <unistd.h>
44#include <stdlib.h>
9ac68eb1 45#include <stdint.h>
8c1a3187 46#include <inttypes.h>
33b34c43
PP
47#include <sys/stat.h>
48#include <dirent.h>
49
6fbd4105
PP
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)
33b34c43 53
6fbd4105
PP
54#ifdef BT_BUILT_IN_PYTHON_PLUGIN_SUPPORT
55#include <babeltrace/plugin/python-plugin-provider-internal.h>
33b34c43 56static
a8ff38ef 57struct bt_plugin_set *(*bt_plugin_python_create_all_from_file_sym)(const char *path) =
6fbd4105
PP
58 bt_plugin_python_create_all_from_file;
59#else /* BT_BUILT_IN_PYTHON_PLUGIN_SUPPORT */
60static GModule *python_plugin_provider_module;
61static
a8ff38ef 62struct bt_plugin_set *(*bt_plugin_python_create_all_from_file_sym)(const char *path);
33b34c43 63
6fbd4105
PP
64__attribute__((constructor)) static
65void init_python_plugin_provider(void) {
8c1a3187 66 BT_LOGD_STR("Loading Python plugin provider module.");
6fbd4105
PP
67 python_plugin_provider_module =
68 g_module_open(PYTHON_PLUGIN_PROVIDER_FILENAME,
69 G_MODULE_BIND_LOCAL);
70 if (!python_plugin_provider_module) {
8c1a3187 71 BT_LOGI("Cannot find `%s`: continuing without Python plugin support.",
6fbd4105
PP
72 PYTHON_PLUGIN_PROVIDER_FILENAME);
73 return;
33b34c43
PP
74 }
75
6fbd4105
PP
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)) {
8c1a3187
PP
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;
33b34c43 84 }
8c1a3187 85
9e0bf9b0 86 BT_LOGI("Loaded Python plugin provider module: addr=%p",
8c1a3187 87 python_plugin_provider_module);
33b34c43
PP
88}
89
6fbd4105
PP
90__attribute__((destructor)) static
91void fini_python_plugin_provider(void) {
92 if (python_plugin_provider_module) {
8c1a3187
PP
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
6fbd4105 100 python_plugin_provider_module = NULL;
6ba0b073 101 }
6ba0b073 102}
6fbd4105 103#endif
6ba0b073 104
a8ff38ef 105extern
544d0515 106int64_t bt_plugin_set_get_plugin_count(struct bt_plugin_set *plugin_set)
a8ff38ef 107{
544d0515 108 int64_t count = -1;
a8ff38ef
PP
109
110 if (!plugin_set) {
8c1a3187 111 BT_LOGW_STR("Invalid parameter: plugin set is NULL.");
a8ff38ef
PP
112 goto end;
113 }
114
9ac68eb1 115 count = (int64_t) plugin_set->plugins->len;
a8ff38ef
PP
116
117end:
118 return count;
119}
120
121extern
122struct bt_plugin *bt_plugin_set_get_plugin(struct bt_plugin_set *plugin_set,
9ac68eb1 123 uint64_t index)
a8ff38ef
PP
124{
125 struct bt_plugin *plugin = NULL;
126
8c1a3187
PP
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);
a8ff38ef
PP
136 goto end;
137 }
138
139 plugin = bt_get(g_ptr_array_index(plugin_set->plugins, index));
140
141end:
142 return plugin;
143}
144
145struct bt_plugin_set *bt_plugin_create_all_from_static(void)
6ba0b073 146{
8c1a3187 147 /* bt_plugin_so_create_all_from_static() logs errors */
55bb57e0 148 return bt_plugin_so_create_all_from_static();
6ba0b073
PP
149}
150
a8ff38ef 151struct bt_plugin_set *bt_plugin_create_all_from_file(const char *path)
33b34c43 152{
a8ff38ef 153 struct bt_plugin_set *plugin_set = NULL;
33b34c43
PP
154
155 if (!path) {
8c1a3187 156 BT_LOGW_STR("Invalid parameter: path is NULL.");
6ba0b073 157 goto end;
33b34c43
PP
158 }
159
8c1a3187 160 BT_LOGD("Creating plugins from file: path=\"%s\"", path);
6ba0b073 161
55bb57e0 162 /* Try shared object plugins */
a8ff38ef
PP
163 plugin_set = bt_plugin_so_create_all_from_file(path);
164 if (plugin_set) {
6ba0b073
PP
165 goto end;
166 }
167
6fbd4105
PP
168 /* Try Python plugins if support is available */
169 if (bt_plugin_python_create_all_from_file_sym) {
a8ff38ef
PP
170 plugin_set = bt_plugin_python_create_all_from_file_sym(path);
171 if (plugin_set) {
6fbd4105
PP
172 goto end;
173 }
6ba0b073
PP
174 }
175
33b34c43 176end:
8c1a3187
PP
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
a8ff38ef 186 return plugin_set;
33b34c43
PP
187}
188
1670bffd
PP
189static void destroy_gstring(void *data)
190{
191 g_string_free(data, TRUE);
192}
193
2b43acf9 194struct bt_plugin *bt_plugin_find(const char *plugin_name)
1670bffd
PP
195{
196 const char *system_plugin_dir;
197 char *home_plugin_dir = NULL;
198 const char *envvar;
199 struct bt_plugin *plugin = NULL;
a8ff38ef 200 struct bt_plugin_set *plugin_set = NULL;
1670bffd
PP
201 GPtrArray *dirs = NULL;
202 int ret;
a8ff38ef 203 size_t i, j;
1670bffd
PP
204
205 if (!plugin_name) {
8c1a3187 206 BT_LOGW_STR("Invalid parameter: plugin name is NULL.");
1670bffd
PP
207 goto end;
208 }
209
8c1a3187
PP
210 BT_LOGD("Finding named plugin in standard directories and built-in plugins: "
211 "name=\"%s\"", plugin_name);
1670bffd
PP
212 dirs = g_ptr_array_new_with_free_func((GDestroyNotify) destroy_gstring);
213 if (!dirs) {
8c1a3187 214 BT_LOGE_STR("Failed to allocate a GPtrArray.");
1670bffd
PP
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) {
8c1a3187 236 BT_LOGE_STR("Failed to append plugin path to array of directories.");
1670bffd
PP
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) {
8c1a3187 247 BT_LOGE_STR("Failed to allocate a GString.");
1670bffd
PP
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) {
8c1a3187 260 BT_LOGE_STR("Failed to allocate a GString.");
1670bffd
PP
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
a8ff38ef 270 BT_PUT(plugin_set);
8c1a3187
PP
271
272 /* bt_plugin_create_all_from_dir() logs details/errors */
c55a9f58 273 plugin_set = bt_plugin_create_all_from_dir(dir->str, BT_FALSE);
a8ff38ef 274 if (!plugin_set) {
8c1a3187
PP
275 BT_LOGD("No plugins found in directory: path=\"%s\"",
276 dir->str);
1670bffd
PP
277 continue;
278 }
279
a8ff38ef
PP
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);
1670bffd 283
a8ff38ef
PP
284 if (strcmp(bt_plugin_get_name(candidate_plugin),
285 plugin_name) == 0) {
8c1a3187
PP
286 BT_LOGD("Plugin found in directory: name=\"%s\", path=\"%s\"",
287 plugin_name, dir->str);
a8ff38ef 288 plugin = bt_get(candidate_plugin);
1670bffd
PP
289 goto end;
290 }
1670bffd 291 }
8c1a3187
PP
292
293 BT_LOGD("Plugin not found in directory: name=\"%s\", path=\"%s\"",
294 plugin_name, dir->str);
1670bffd
PP
295 }
296
a8ff38ef
PP
297 bt_put(plugin_set);
298 plugin_set = bt_plugin_create_all_from_static();
8c1a3187
PP
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);
a8ff38ef 303
8c1a3187
PP
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 }
1670bffd 311 }
1670bffd
PP
312 }
313
314end:
315 free(home_plugin_dir);
a8ff38ef 316 bt_put(plugin_set);
1670bffd
PP
317
318 if (dirs) {
319 g_ptr_array_free(dirs, TRUE);
320 }
321
8c1a3187
PP
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
1670bffd
PP
331 return plugin;
332}
333
2b43acf9
PP
334struct 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
8c1a3187
PP
341 if (!plugin_name) {
342 BT_LOGW_STR("Invalid parameter: plugin name is NULL.");
2b43acf9
PP
343 goto end;
344 }
345
8c1a3187
PP
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);
2b43acf9
PP
354 plugin = bt_plugin_find(plugin_name);
355 if (!plugin) {
8c1a3187 356 BT_LOGD_STR("Plugin not found.");
2b43acf9
PP
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);
8c1a3187
PP
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 }
2b43acf9
PP
367
368end:
369 bt_put(plugin);
370 return comp_cls;
371}
372
33b34c43
PP
373/* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */
374static
375struct 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
390static
391enum bt_plugin_status bt_plugin_create_append_all_from_dir(
a8ff38ef 392 struct bt_plugin_set *plugin_set, const char *path,
c55a9f58 393 bt_bool recurse)
33b34c43
PP
394{
395 DIR *directory = NULL;
396 struct dirent *entry = NULL, *result = NULL;
397 char *file_path = NULL;
6ba0b073 398 size_t path_len;
33b34c43
PP
399 enum bt_plugin_status ret = BT_PLUGIN_STATUS_OK;
400
6ba0b073 401 if (!path) {
8c1a3187 402 BT_LOGW_STR("Invalid parameter: path is NULL.");
6ba0b073
PP
403 ret = BT_PLUGIN_STATUS_ERROR;
404 goto end;
405 }
406
407 path_len = strlen(path);
33b34c43 408 if (path_len >= PATH_MAX) {
8c1a3187
PP
409 BT_LOGW("Invalid parameter: path length is too large: "
410 "path-length=%zu", path_len);
33b34c43
PP
411 ret = BT_PLUGIN_STATUS_ERROR;
412 goto end;
413 }
414
415 entry = alloc_dirent(path);
416 if (!entry) {
8c1a3187 417 BT_LOGE_STR("Failed to allocate a directory entry.");
33b34c43
PP
418 ret = BT_PLUGIN_STATUS_ERROR;
419 goto end;
420 }
421
422 file_path = zmalloc(PATH_MAX);
423 if (!file_path) {
8c1a3187 424 BT_LOGE("Failed to allocate %zu bytes.", (size_t) PATH_MAX);
33b34c43
PP
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) {
8c1a3187
PP
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
dbd7f7e9 444 BT_LOGW("Cannot open directory: %s: "
8c1a3187
PP
445 "path=\"%s\", errno=%d",
446 strerror(errno), file_path, errno);
33b34c43
PP
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
8c1a3187
PP
457 if (strcmp(result->d_name, ".") == 0 ||
458 strcmp(result->d_name, "..") == 0) {
459 continue;
460 }
461
33b34c43
PP
462 if (result->d_name[0] == '.') {
463 /* Skip hidden files, . and .. */
8c1a3187
PP
464 BT_LOGV("Skipping hidden file: path=\"%s/%s\"",
465 path, result->d_name);
33b34c43
PP
466 continue;
467 }
468
469 file_name_len = strlen(result->d_name);
470
471 if (path_len + file_name_len >= PATH_MAX) {
8c1a3187
PP
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));
33b34c43
PP
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';
33b34c43
PP
481 stat_ret = stat(file_path, &st);
482 if (stat_ret < 0) {
483 /* Continue to next file / directory. */
8c1a3187
PP
484 BT_LOGD("Cannot get file information: %s: continuing: "
485 "path=\"%s\", errno=%d",
486 strerror(errno), file_path, errno);
33b34c43
PP
487 continue;
488 }
489
490 if (S_ISDIR(st.st_mode) && recurse) {
a8ff38ef 491 ret = bt_plugin_create_append_all_from_dir(plugin_set,
c55a9f58 492 file_path, BT_TRUE);
33b34c43 493 if (ret < 0) {
8c1a3187
PP
494 BT_LOGW("Cannot recurse into directory to find plugins: "
495 "path=\"%s\", ret=%d", file_path, ret);
33b34c43
PP
496 goto end;
497 }
498 } else if (S_ISREG(st.st_mode)) {
a8ff38ef 499 struct bt_plugin_set *plugins_from_file =
6ba0b073 500 bt_plugin_create_all_from_file(file_path);
33b34c43 501
6ba0b073 502 if (plugins_from_file) {
a8ff38ef
PP
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);
6ba0b073 508
8c1a3187
PP
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));
a8ff38ef
PP
513 bt_plugin_set_add_plugin(plugin_set,
514 plugin);
6ba0b073
PP
515 }
516
a8ff38ef 517 bt_put(plugins_from_file);
33b34c43
PP
518 }
519 }
520 }
8c1a3187 521
33b34c43
PP
522end:
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 */
8c1a3187
PP
529 BT_LOGE("Cannot close directory entry: %s: "
530 "path=\"%s\", errno=%d",
531 strerror(errno), path, errno);
33b34c43
PP
532 }
533 }
8c1a3187 534
33b34c43
PP
535 free(entry);
536 free(file_path);
537 return ret;
538}
539
a8ff38ef 540struct bt_plugin_set *bt_plugin_create_all_from_dir(const char *path,
c55a9f58 541 bt_bool recurse)
33b34c43 542{
a8ff38ef 543 struct bt_plugin_set *plugin_set;
33b34c43
PP
544 enum bt_plugin_status status;
545
8c1a3187
PP
546 BT_LOGD("Creating all plugins in directory: path=\"%s\", recurse=%d",
547 path, recurse);
a8ff38ef
PP
548 plugin_set = bt_plugin_set_create();
549 if (!plugin_set) {
8c1a3187 550 BT_LOGE_STR("Cannot create empty plugin set.");
a8ff38ef
PP
551 goto error;
552 }
553
33b34c43 554 /* Append found plugins to array */
a8ff38ef 555 status = bt_plugin_create_append_all_from_dir(plugin_set, path,
33b34c43
PP
556 recurse);
557 if (status < 0) {
8c1a3187 558 BT_LOGW("Cannot append plugins found in directory: "
dbd7f7e9
PP
559 "path=\"%s\", status=%s",
560 path, bt_plugin_status_string(status));
33b34c43
PP
561 goto error;
562 }
563
8c1a3187
PP
564 BT_LOGD("Created %u plugins from directory: count=%u, path=\"%s\"",
565 plugin_set->plugins->len, plugin_set->plugins->len, path);
33b34c43
PP
566 goto end;
567
568error:
a8ff38ef 569 BT_PUT(plugin_set);
33b34c43
PP
570
571end:
a8ff38ef 572 return plugin_set;
33b34c43
PP
573}
574
33b34c43
PP
575const char *bt_plugin_get_name(struct bt_plugin *plugin)
576{
8c1a3187
PP
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
588end:
589 return val;
33b34c43
PP
590}
591
592const char *bt_plugin_get_author(struct bt_plugin *plugin)
593{
8c1a3187
PP
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
605end:
606 return val;
33b34c43
PP
607}
608
609const char *bt_plugin_get_license(struct bt_plugin *plugin)
610{
8c1a3187
PP
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
622end:
623 return val;
33b34c43
PP
624}
625
626const char *bt_plugin_get_path(struct bt_plugin *plugin)
627{
8c1a3187
PP
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
639end:
640 return val;
33b34c43
PP
641}
642
643const char *bt_plugin_get_description(struct bt_plugin *plugin)
644{
8c1a3187
PP
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
656end:
657 return val;
33b34c43
PP
658}
659
b6de043b
PP
660enum 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
8c1a3187
PP
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);
b6de043b
PP
674 status = BT_PLUGIN_STATUS_ERROR;
675 goto end;
676 }
677
678 if (major) {
55bb57e0 679 *major = plugin->info.version.major;
b6de043b
PP
680 }
681
682 if (minor) {
55bb57e0 683 *minor = plugin->info.version.minor;
b6de043b
PP
684 }
685
686 if (patch) {
55bb57e0 687 *patch = plugin->info.version.patch;
b6de043b
PP
688 }
689
690 if (extra) {
55bb57e0 691 *extra = plugin->info.version.extra->str;
b6de043b
PP
692 }
693
694end:
695 return status;
696}
697
544d0515 698int64_t bt_plugin_get_component_class_count(struct bt_plugin *plugin)
33b34c43 699{
9ac68eb1 700 return plugin ? plugin->comp_classes->len : (int64_t) -1;
33b34c43
PP
701}
702
9ac68eb1
PP
703struct bt_component_class *bt_plugin_get_component_class_by_index(
704 struct bt_plugin *plugin, uint64_t index)
33b34c43
PP
705{
706 struct bt_component_class *comp_class = NULL;
707
8c1a3187
PP
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);
33b34c43
PP
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
724error:
725 BT_PUT(comp_class);
726
727end:
728 return comp_class;
729}
730
731struct bt_component_class *bt_plugin_get_component_class_by_name_and_type(
732 struct bt_plugin *plugin, const char *name,
d3e4dcd8 733 enum bt_component_class_type type)
33b34c43
PP
734{
735 struct bt_component_class *comp_class = NULL;
736 size_t i;
737
8c1a3187
PP
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.");
33b34c43
PP
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);
d3e4dcd8 753 enum bt_component_class_type comp_class_cand_type =
33b34c43
PP
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
768error:
769 BT_PUT(comp_class);
770
771end:
772 return comp_class;
773}
774
33b34c43
PP
775enum 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;
33b34c43
PP
780 int comp_class_index = -1;
781
8c1a3187
PP
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));
33b34c43
PP
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) {
8c1a3187
PP
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),
33b34c43 809 bt_component_class_get_name(comp_class),
8c1a3187
PP
810 bt_component_class_type_string(
811 bt_component_class_get_type(comp_class)));
33b34c43
PP
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
55bb57e0
PP
819 /* Special case for a shared object plugin */
820 if (plugin->type == BT_PLUGIN_TYPE_SO) {
3230ee6b 821 bt_plugin_so_on_add_component_class(plugin, comp_class);
33b34c43
PP
822 }
823
8c1a3187
PP
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)));
33b34c43
PP
833 goto end;
834
835error:
33b34c43
PP
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
844end:
845 bt_put(comp_class_dup);
846 return status;
847}
This page took 0.069897 seconds and 4 git commands to generate.