text.pretty: create an event string instead of using fprintf()/fputs()
[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
PP
85
86 BT_LOGD("Loaded Python plugin provider module: addr=%p",
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
444 BT_LOGE("Cannot open directory: %s: "
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
PP
558 BT_LOGW("Cannot append plugins found in directory: "
559 "status=%s", bt_plugin_status_string(status));
33b34c43
PP
560 goto error;
561 }
562
8c1a3187
PP
563 BT_LOGD("Created %u plugins from directory: count=%u, path=\"%s\"",
564 plugin_set->plugins->len, plugin_set->plugins->len, path);
33b34c43
PP
565 goto end;
566
567error:
a8ff38ef 568 BT_PUT(plugin_set);
33b34c43
PP
569
570end:
a8ff38ef 571 return plugin_set;
33b34c43
PP
572}
573
33b34c43
PP
574const char *bt_plugin_get_name(struct bt_plugin *plugin)
575{
8c1a3187
PP
576 const char *val = NULL;
577
578 if (!plugin) {
579 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
580 goto end;
581 }
582
583 if (plugin->info.name_set) {
584 val = plugin->info.name->str;
585 }
586
587end:
588 return val;
33b34c43
PP
589}
590
591const char *bt_plugin_get_author(struct bt_plugin *plugin)
592{
8c1a3187
PP
593 const char *val = NULL;
594
595 if (!plugin) {
596 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
597 goto end;
598 }
599
600 if (plugin->info.author_set) {
601 val = plugin->info.author->str;
602 }
603
604end:
605 return val;
33b34c43
PP
606}
607
608const char *bt_plugin_get_license(struct bt_plugin *plugin)
609{
8c1a3187
PP
610 const char *val = NULL;
611
612 if (!plugin) {
613 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
614 goto end;
615 }
616
617 if (plugin->info.license_set) {
618 val = plugin->info.license->str;
619 }
620
621end:
622 return val;
33b34c43
PP
623}
624
625const char *bt_plugin_get_path(struct bt_plugin *plugin)
626{
8c1a3187
PP
627 const char *val = NULL;
628
629 if (!plugin) {
630 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
631 goto end;
632 }
633
634 if (plugin->info.path_set) {
635 val = plugin->info.path->str;
636 }
637
638end:
639 return val;
33b34c43
PP
640}
641
642const char *bt_plugin_get_description(struct bt_plugin *plugin)
643{
8c1a3187
PP
644 const char *val = NULL;
645
646 if (!plugin) {
647 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
648 goto end;
649 }
650
651 if (plugin->info.description_set) {
652 val = plugin->info.description->str;
653 }
654
655end:
656 return val;
33b34c43
PP
657}
658
b6de043b
PP
659enum bt_plugin_status bt_plugin_get_version(struct bt_plugin *plugin,
660 unsigned int *major, unsigned int *minor, unsigned int *patch,
661 const char **extra)
662{
663 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
664
8c1a3187
PP
665 if (!plugin) {
666 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
667 status = BT_PLUGIN_STATUS_ERROR;
668 goto end;
669 }
670
671 if (!plugin->info.version_set) {
672 BT_LOGV("Plugin's version is not set: addr=%p", plugin);
b6de043b
PP
673 status = BT_PLUGIN_STATUS_ERROR;
674 goto end;
675 }
676
677 if (major) {
55bb57e0 678 *major = plugin->info.version.major;
b6de043b
PP
679 }
680
681 if (minor) {
55bb57e0 682 *minor = plugin->info.version.minor;
b6de043b
PP
683 }
684
685 if (patch) {
55bb57e0 686 *patch = plugin->info.version.patch;
b6de043b
PP
687 }
688
689 if (extra) {
55bb57e0 690 *extra = plugin->info.version.extra->str;
b6de043b
PP
691 }
692
693end:
694 return status;
695}
696
544d0515 697int64_t bt_plugin_get_component_class_count(struct bt_plugin *plugin)
33b34c43 698{
9ac68eb1 699 return plugin ? plugin->comp_classes->len : (int64_t) -1;
33b34c43
PP
700}
701
9ac68eb1
PP
702struct bt_component_class *bt_plugin_get_component_class_by_index(
703 struct bt_plugin *plugin, uint64_t index)
33b34c43
PP
704{
705 struct bt_component_class *comp_class = NULL;
706
8c1a3187
PP
707 if (!plugin) {
708 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
709 goto error;
710 }
711
712 if (index >= plugin->comp_classes->len) {
713 BT_LOGW("Invalid parameter: index is out of bounds: "
714 "addr=%p, index=%" PRIu64 ", count=%u",
715 plugin, index, plugin->comp_classes->len);
33b34c43
PP
716 goto error;
717 }
718
719 comp_class = g_ptr_array_index(plugin->comp_classes, index);
720 bt_get(comp_class);
721 goto end;
722
723error:
724 BT_PUT(comp_class);
725
726end:
727 return comp_class;
728}
729
730struct bt_component_class *bt_plugin_get_component_class_by_name_and_type(
731 struct bt_plugin *plugin, const char *name,
d3e4dcd8 732 enum bt_component_class_type type)
33b34c43
PP
733{
734 struct bt_component_class *comp_class = NULL;
735 size_t i;
736
8c1a3187
PP
737 if (!plugin) {
738 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
739 goto error;
740 }
741
742 if (!name) {
743 BT_LOGW_STR("Invalid parameter: name is NULL.");
33b34c43
PP
744 goto error;
745 }
746
747 for (i = 0; i < plugin->comp_classes->len; i++) {
748 struct bt_component_class *comp_class_candidate =
749 g_ptr_array_index(plugin->comp_classes, i);
750 const char *comp_class_cand_name =
751 bt_component_class_get_name(comp_class_candidate);
d3e4dcd8 752 enum bt_component_class_type comp_class_cand_type =
33b34c43
PP
753 bt_component_class_get_type(comp_class_candidate);
754
755 assert(comp_class_cand_name);
756 assert(comp_class_cand_type >= 0);
757
758 if (strcmp(name, comp_class_cand_name) == 0 &&
759 comp_class_cand_type == type) {
760 comp_class = bt_get(comp_class_candidate);
761 break;
762 }
763 }
764
765 goto end;
766
767error:
768 BT_PUT(comp_class);
769
770end:
771 return comp_class;
772}
773
33b34c43
PP
774enum bt_plugin_status bt_plugin_add_component_class(
775 struct bt_plugin *plugin, struct bt_component_class *comp_class)
776{
777 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
778 struct bt_component_class *comp_class_dup = NULL;
33b34c43
PP
779 int comp_class_index = -1;
780
8c1a3187
PP
781 if (!plugin) {
782 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
783 goto error;
784 }
785
786 if (!comp_class) {
787 BT_LOGW_STR("Invalid parameter: component class is NULL.");
788 goto error;
789 }
790
791 if (plugin->frozen) {
792 BT_LOGW("Invalid parameter: plugin is frozen: "
793 "addr=%p, name=\"%s\"", plugin,
794 bt_plugin_get_name(plugin));
33b34c43
PP
795 goto error;
796 }
797
798 /* Check for duplicate */
799 comp_class_dup = bt_plugin_get_component_class_by_name_and_type(plugin,
800 bt_component_class_get_name(comp_class),
801 bt_component_class_get_type(comp_class));
802 if (comp_class_dup) {
8c1a3187
PP
803 BT_LOGW("Invalid parameter: a component class with this name and type already exists in the plugin: "
804 "plugin-addr=%p, plugin-name=\"%s\", plugin-path=\"%s\", "
805 "comp-class-name=\"%s\", comp-class-type=%s",
806 plugin, bt_plugin_get_name(plugin),
807 bt_plugin_get_path(plugin),
33b34c43 808 bt_component_class_get_name(comp_class),
8c1a3187
PP
809 bt_component_class_type_string(
810 bt_component_class_get_type(comp_class)));
33b34c43
PP
811 goto error;
812 }
813
814 /* Add new component class */
815 comp_class_index = plugin->comp_classes->len;
816 g_ptr_array_add(plugin->comp_classes, bt_get(comp_class));
817
55bb57e0
PP
818 /* Special case for a shared object plugin */
819 if (plugin->type == BT_PLUGIN_TYPE_SO) {
3230ee6b 820 bt_plugin_so_on_add_component_class(plugin, comp_class);
33b34c43
PP
821 }
822
8c1a3187
PP
823 BT_LOGD("Added component class to plugin: "
824 "plugin-addr=%p, plugin-name=\"%s\", plugin-path=\"%s\", "
825 "comp-class-addr=%p, comp-class-name=\"%s\", comp-class-type=%s",
826 plugin, bt_plugin_get_name(plugin),
827 bt_plugin_get_path(plugin),
828 comp_class,
829 bt_component_class_get_name(comp_class),
830 bt_component_class_type_string(
831 bt_component_class_get_type(comp_class)));
33b34c43
PP
832 goto end;
833
834error:
33b34c43
PP
835 /* Remove entry from plugin's component classes (if added) */
836 if (comp_class_index >= 0) {
837 g_ptr_array_remove_index(plugin->comp_classes,
838 comp_class_index);
839 }
840
841 status = BT_PLUGIN_STATUS_ERROR;
842
843end:
844 bt_put(comp_class_dup);
845 return status;
846}
This page took 0.074305 seconds and 4 git commands to generate.