tap-driver.sh: flush stdout after each test result
[babeltrace.git] / lib / plugin / plugin-so.c
1 /*
2 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
3 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 *
5 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26 #define BT_LOG_TAG "PLUGIN-SO"
27 #include <babeltrace2/lib-logging-internal.h>
28
29 #include <babeltrace2/assert-internal.h>
30 #include <babeltrace2/assert-pre-internal.h>
31 #include <babeltrace2/compiler-internal.h>
32 #include <babeltrace2/plugin/plugin-internal.h>
33 #include <babeltrace2/plugin/plugin-so-internal.h>
34 #include <babeltrace2/plugin/plugin-dev.h>
35 #include <babeltrace2/plugin/plugin-internal.h>
36 #include <babeltrace2/graph/component-class-internal.h>
37 #include <babeltrace2/graph/component-class.h>
38 #include <babeltrace2/graph/component-class-source.h>
39 #include <babeltrace2/graph/component-class-filter.h>
40 #include <babeltrace2/graph/component-class-sink.h>
41 #include <babeltrace2/types.h>
42 #include <babeltrace2/list-internal.h>
43 #include <string.h>
44 #include <stdlib.h>
45 #include <glib.h>
46 #include <gmodule.h>
47
48 #define NATIVE_PLUGIN_SUFFIX "." G_MODULE_SUFFIX
49 #define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
50 #define LIBTOOL_PLUGIN_SUFFIX ".la"
51 #define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
52
53 #define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
54 sizeof(LIBTOOL_PLUGIN_SUFFIX))
55
56 BT_PLUGIN_MODULE();
57
58 /*
59 * This list, global to the library, keeps all component classes that
60 * have a reference to their shared library handles. It allows iteration
61 * on all component classes still present when the destructor executes
62 * to release the shared library handle references they might still have.
63 *
64 * The list items are the component classes created with
65 * bt_plugin_add_component_class(). They keep the shared library handle
66 * object created by their plugin alive so that the plugin's code is
67 * not discarded when it could still be in use by living components
68 * created from those component classes:
69 *
70 * [component] --ref-> [component class]-> [shlib handle]
71 *
72 * It allows this use-case:
73 *
74 * my_plugins = bt_plugin_find_all_from_file("/path/to/my-plugin.so");
75 * // instantiate components from a plugin's component classes
76 * // put plugins and free my_plugins here
77 * // user code of instantiated components still exists
78 *
79 * An entry is removed from this list when a component class is
80 * destroyed thanks to a custom destroy listener. When the entry is
81 * removed, the entry is removed from the list, and we release the
82 * reference on the shlib handle. Assuming the original plugin object
83 * which contained some component classes is put first, when the last
84 * component class is removed from this list, the shared library handle
85 * object's reference count falls to zero and the shared library is
86 * finally closed.
87 */
88
89 static
90 BT_LIST_HEAD(component_class_list);
91
92 __attribute__((destructor)) static
93 void fini_comp_class_list(void)
94 {
95 struct bt_component_class *comp_class, *tmp;
96
97 bt_list_for_each_entry_safe(comp_class, tmp, &component_class_list, node) {
98 bt_list_del(&comp_class->node);
99 BT_OBJECT_PUT_REF_AND_RESET(comp_class->so_handle);
100 }
101
102 BT_LOGD_STR("Released references from all component classes to shared library handles.");
103 }
104
105 static inline
106 const char *bt_self_plugin_status_string(enum bt_self_plugin_status status)
107 {
108 switch (status) {
109 case BT_SELF_PLUGIN_STATUS_OK:
110 return "BT_SELF_PLUGIN_STATUS_OK";
111 case BT_SELF_PLUGIN_STATUS_ERROR:
112 return "BT_SELF_PLUGIN_STATUS_ERROR";
113 case BT_SELF_PLUGIN_STATUS_NOMEM:
114 return "BT_SELF_PLUGIN_STATUS_NOMEM";
115 default:
116 return "(unknown)";
117 }
118 }
119
120 static
121 void bt_plugin_so_shared_lib_handle_destroy(struct bt_object *obj)
122 {
123 struct bt_plugin_so_shared_lib_handle *shared_lib_handle;
124
125 BT_ASSERT(obj);
126 shared_lib_handle = container_of(obj,
127 struct bt_plugin_so_shared_lib_handle, base);
128 const char *path = shared_lib_handle->path ?
129 shared_lib_handle->path->str : NULL;
130
131 BT_LOGD("Destroying shared library handle: addr=%p, path=\"%s\"",
132 shared_lib_handle, path);
133
134 if (shared_lib_handle->init_called && shared_lib_handle->exit) {
135 BT_LOGD_STR("Calling user's plugin exit function.");
136 shared_lib_handle->exit();
137 BT_LOGD_STR("User function returned.");
138 }
139
140 if (shared_lib_handle->module) {
141 #ifndef NDEBUG
142 /*
143 * Valgrind shows incomplete stack traces when
144 * dynamically loaded libraries are closed before it
145 * finishes. Use the BABELTRACE_NO_DLCLOSE in a debug
146 * build to avoid this.
147 */
148 const char *var = getenv("BABELTRACE_NO_DLCLOSE");
149
150 if (!var || strcmp(var, "1") != 0) {
151 #endif
152 BT_LOGD("Closing GModule: path=\"%s\"", path);
153
154 if (!g_module_close(shared_lib_handle->module)) {
155 BT_LOGE("Cannot close GModule: %s: path=\"%s\"",
156 g_module_error(), path);
157 }
158
159 shared_lib_handle->module = NULL;
160 #ifndef NDEBUG
161 } else {
162 BT_LOGD("Not closing GModule because `BABELTRACE_NO_DLCLOSE=1`: "
163 "path=\"%s\"", path);
164 }
165 #endif
166 }
167
168 if (shared_lib_handle->path) {
169 g_string_free(shared_lib_handle->path, TRUE);
170 shared_lib_handle->path = NULL;
171 }
172
173 g_free(shared_lib_handle);
174 }
175
176 static
177 struct bt_plugin_so_shared_lib_handle *bt_plugin_so_shared_lib_handle_create(
178 const char *path)
179 {
180 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
181
182 BT_LOGD("Creating shared library handle: path=\"%s\"", path);
183 shared_lib_handle = g_new0(struct bt_plugin_so_shared_lib_handle, 1);
184 if (!shared_lib_handle) {
185 BT_LOGE_STR("Failed to allocate one shared library handle.");
186 goto error;
187 }
188
189 bt_object_init_shared(&shared_lib_handle->base,
190 bt_plugin_so_shared_lib_handle_destroy);
191
192 if (!path) {
193 goto end;
194 }
195
196 shared_lib_handle->path = g_string_new(path);
197 if (!shared_lib_handle->path) {
198 BT_LOGE_STR("Failed to allocate a GString.");
199 goto error;
200 }
201
202 shared_lib_handle->module = g_module_open(path, G_MODULE_BIND_LOCAL);
203 if (!shared_lib_handle->module) {
204 /*
205 * DEBUG-level logging because we're only _trying_ to
206 * open this file as a Babeltrace plugin: if it's not,
207 * it's not an error. And because this can be tried
208 * during bt_plugin_find_all_from_dir(), it's not even
209 * a warning.
210 */
211 BT_LOGD("Cannot open GModule: %s: path=\"%s\"",
212 g_module_error(), path);
213 goto error;
214 }
215
216 goto end;
217
218 error:
219 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
220
221 end:
222 if (shared_lib_handle) {
223 BT_LOGD("Created shared library handle: path=\"%s\", addr=%p",
224 path, shared_lib_handle);
225 }
226
227 return shared_lib_handle;
228 }
229
230 static
231 void bt_plugin_so_destroy_spec_data(struct bt_plugin *plugin)
232 {
233 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
234
235 if (!plugin->spec_data) {
236 return;
237 }
238
239 BT_ASSERT(plugin->type == BT_PLUGIN_TYPE_SO);
240 BT_ASSERT(spec);
241 BT_OBJECT_PUT_REF_AND_RESET(spec->shared_lib_handle);
242 g_free(plugin->spec_data);
243 plugin->spec_data = NULL;
244 }
245
246 /*
247 * This function does the following:
248 *
249 * 1. Iterate on the plugin descriptor attributes section and set the
250 * plugin's attributes depending on the attribute types. This
251 * includes the name of the plugin, its description, and its
252 * initialization function, for example.
253 *
254 * 2. Iterate on the component class descriptors section and create one
255 * "full descriptor" (temporary structure) for each one that is found
256 * and attached to our plugin descriptor.
257 *
258 * 3. Iterate on the component class descriptor attributes section and
259 * set the corresponding full descriptor's attributes depending on
260 * the attribute types. This includes the description of the
261 * component class, as well as its initialization and destroy
262 * methods.
263 *
264 * 4. Call the user's plugin initialization function, if any is
265 * defined.
266 *
267 * 5. For each full component class descriptor, create a component class
268 * object, set its optional attributes, and add it to the plugin
269 * object.
270 *
271 * 6. Freeze the plugin object.
272 */
273 static
274 enum bt_plugin_status bt_plugin_so_init(
275 struct bt_plugin *plugin,
276 const struct __bt_plugin_descriptor *descriptor,
277 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
278 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
279 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
280 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
281 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
282 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
283 {
284 /*
285 * This structure's members point to the plugin's memory
286 * (do NOT free).
287 */
288 struct comp_class_full_descriptor {
289 const struct __bt_plugin_component_class_descriptor *descriptor;
290 const char *description;
291 const char *help;
292
293 union {
294 struct {
295 bt_component_class_source_init_method init;
296 bt_component_class_source_finalize_method finalize;
297 bt_component_class_source_query_method query;
298 bt_component_class_source_accept_output_port_connection_method accept_output_port_connection;
299 bt_component_class_source_output_port_connected_method output_port_connected;
300 bt_component_class_source_message_iterator_init_method msg_iter_init;
301 bt_component_class_source_message_iterator_finalize_method msg_iter_finalize;
302 bt_component_class_source_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin;
303 bt_component_class_source_message_iterator_seek_beginning_method msg_iter_seek_beginning;
304 bt_component_class_source_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin;
305 bt_component_class_source_message_iterator_can_seek_beginning_method msg_iter_can_seek_beginning;
306 } source;
307
308 struct {
309 bt_component_class_filter_init_method init;
310 bt_component_class_filter_finalize_method finalize;
311 bt_component_class_filter_query_method query;
312 bt_component_class_filter_accept_input_port_connection_method accept_input_port_connection;
313 bt_component_class_filter_accept_output_port_connection_method accept_output_port_connection;
314 bt_component_class_filter_input_port_connected_method input_port_connected;
315 bt_component_class_filter_output_port_connected_method output_port_connected;
316 bt_component_class_filter_message_iterator_init_method msg_iter_init;
317 bt_component_class_filter_message_iterator_finalize_method msg_iter_finalize;
318 bt_component_class_filter_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin;
319 bt_component_class_filter_message_iterator_seek_beginning_method msg_iter_seek_beginning;
320 bt_component_class_filter_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin;
321 bt_component_class_filter_message_iterator_can_seek_beginning_method msg_iter_can_seek_beginning;
322 } filter;
323
324 struct {
325 bt_component_class_sink_init_method init;
326 bt_component_class_sink_finalize_method finalize;
327 bt_component_class_sink_query_method query;
328 bt_component_class_sink_accept_input_port_connection_method accept_input_port_connection;
329 bt_component_class_sink_input_port_connected_method input_port_connected;
330 bt_component_class_sink_graph_is_configured_method graph_is_configured;
331 } sink;
332 } methods;
333 };
334
335 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
336 struct __bt_plugin_descriptor_attribute const * const *cur_attr_ptr;
337 struct __bt_plugin_component_class_descriptor const * const *cur_cc_descr_ptr;
338 struct __bt_plugin_component_class_descriptor_attribute const * const *cur_cc_descr_attr_ptr;
339 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
340 GArray *comp_class_full_descriptors;
341 size_t i;
342 int ret;
343
344 BT_LOGD("Initializing plugin object from descriptors found in sections: "
345 "plugin-addr=%p, plugin-path=\"%s\", "
346 "attrs-begin-addr=%p, attrs-end-addr=%p, "
347 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
348 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p",
349 plugin,
350 spec->shared_lib_handle->path ?
351 spec->shared_lib_handle->path->str : NULL,
352 attrs_begin, attrs_end,
353 cc_descriptors_begin, cc_descriptors_end,
354 cc_descr_attrs_begin, cc_descr_attrs_end);
355 comp_class_full_descriptors = g_array_new(FALSE, TRUE,
356 sizeof(struct comp_class_full_descriptor));
357 if (!comp_class_full_descriptors) {
358 BT_LOGE_STR("Failed to allocate a GArray.");
359 status = BT_PLUGIN_STATUS_ERROR;
360 goto end;
361 }
362
363 /* Set mandatory attributes */
364 spec->descriptor = descriptor;
365 bt_plugin_set_name(plugin, descriptor->name);
366
367 /*
368 * Find and set optional attributes attached to this plugin
369 * descriptor.
370 */
371 for (cur_attr_ptr = attrs_begin; cur_attr_ptr != attrs_end; cur_attr_ptr++) {
372 const struct __bt_plugin_descriptor_attribute *cur_attr =
373 *cur_attr_ptr;
374
375 if (cur_attr == NULL) {
376 continue;
377 }
378
379 if (cur_attr->plugin_descriptor != descriptor) {
380 continue;
381 }
382
383 switch (cur_attr->type) {
384 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT:
385 spec->init = cur_attr->value.init;
386 break;
387 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT:
388 spec->shared_lib_handle->exit = cur_attr->value.exit;
389 break;
390 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR:
391 bt_plugin_set_author(plugin, cur_attr->value.author);
392 break;
393 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE:
394 bt_plugin_set_license(plugin, cur_attr->value.license);
395 break;
396 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
397 bt_plugin_set_description(plugin, cur_attr->value.description);
398 break;
399 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION:
400 bt_plugin_set_version(plugin,
401 (unsigned int) cur_attr->value.version.major,
402 (unsigned int) cur_attr->value.version.minor,
403 (unsigned int) cur_attr->value.version.patch,
404 cur_attr->value.version.extra);
405 break;
406 default:
407 /*
408 * WARN-level logging because this should not
409 * happen with the appropriate ABI version. If
410 * we're here, we know that for the reported
411 * version of the ABI, this attribute is
412 * unknown.
413 */
414 BT_LOGW("Ignoring unknown plugin descriptor attribute: "
415 "plugin-path=\"%s\", plugin-name=\"%s\", "
416 "attr-type-name=\"%s\", attr-type-id=%d",
417 spec->shared_lib_handle->path ?
418 spec->shared_lib_handle->path->str :
419 NULL,
420 descriptor->name, cur_attr->type_name,
421 cur_attr->type);
422 break;
423 }
424 }
425
426 /*
427 * Find component class descriptors attached to this plugin
428 * descriptor and initialize corresponding full component class
429 * descriptors in the array.
430 */
431 for (cur_cc_descr_ptr = cc_descriptors_begin; cur_cc_descr_ptr != cc_descriptors_end; cur_cc_descr_ptr++) {
432 const struct __bt_plugin_component_class_descriptor *cur_cc_descr =
433 *cur_cc_descr_ptr;
434 struct comp_class_full_descriptor full_descriptor = {0};
435
436 if (cur_cc_descr == NULL) {
437 continue;
438 }
439
440 if (cur_cc_descr->plugin_descriptor != descriptor) {
441 continue;
442 }
443
444 full_descriptor.descriptor = cur_cc_descr;
445 g_array_append_val(comp_class_full_descriptors,
446 full_descriptor);
447 }
448
449 /*
450 * Find component class descriptor attributes attached to this
451 * plugin descriptor and update corresponding full component
452 * class descriptors in the array.
453 */
454 for (cur_cc_descr_attr_ptr = cc_descr_attrs_begin; cur_cc_descr_attr_ptr != cc_descr_attrs_end; cur_cc_descr_attr_ptr++) {
455 const struct __bt_plugin_component_class_descriptor_attribute *cur_cc_descr_attr =
456 *cur_cc_descr_attr_ptr;
457 enum bt_component_class_type cc_type;
458
459 if (cur_cc_descr_attr == NULL) {
460 continue;
461 }
462
463 if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor !=
464 descriptor) {
465 continue;
466 }
467
468 cc_type = cur_cc_descr_attr->comp_class_descriptor->type;
469
470 /* Find the corresponding component class descriptor entry */
471 for (i = 0; i < comp_class_full_descriptors->len; i++) {
472 struct comp_class_full_descriptor *cc_full_descr =
473 &g_array_index(comp_class_full_descriptors,
474 struct comp_class_full_descriptor, i);
475
476 if (cur_cc_descr_attr->comp_class_descriptor !=
477 cc_full_descr->descriptor) {
478 continue;
479 }
480
481 switch (cur_cc_descr_attr->type) {
482 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
483 cc_full_descr->description =
484 cur_cc_descr_attr->value.description;
485 break;
486 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP:
487 cc_full_descr->help =
488 cur_cc_descr_attr->value.help;
489 break;
490 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INIT_METHOD:
491 switch (cc_type) {
492 case BT_COMPONENT_CLASS_TYPE_SOURCE:
493 cc_full_descr->methods.source.init =
494 cur_cc_descr_attr->value.source_init_method;
495 break;
496 case BT_COMPONENT_CLASS_TYPE_FILTER:
497 cc_full_descr->methods.filter.init =
498 cur_cc_descr_attr->value.filter_init_method;
499 break;
500 case BT_COMPONENT_CLASS_TYPE_SINK:
501 cc_full_descr->methods.sink.init =
502 cur_cc_descr_attr->value.sink_init_method;
503 break;
504 default:
505 abort();
506 }
507 break;
508 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD:
509 switch (cc_type) {
510 case BT_COMPONENT_CLASS_TYPE_SOURCE:
511 cc_full_descr->methods.source.finalize =
512 cur_cc_descr_attr->value.source_finalize_method;
513 break;
514 case BT_COMPONENT_CLASS_TYPE_FILTER:
515 cc_full_descr->methods.filter.finalize =
516 cur_cc_descr_attr->value.filter_finalize_method;
517 break;
518 case BT_COMPONENT_CLASS_TYPE_SINK:
519 cc_full_descr->methods.sink.finalize =
520 cur_cc_descr_attr->value.sink_finalize_method;
521 break;
522 default:
523 abort();
524 }
525 break;
526 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD:
527 switch (cc_type) {
528 case BT_COMPONENT_CLASS_TYPE_SOURCE:
529 cc_full_descr->methods.source.query =
530 cur_cc_descr_attr->value.source_query_method;
531 break;
532 case BT_COMPONENT_CLASS_TYPE_FILTER:
533 cc_full_descr->methods.filter.query =
534 cur_cc_descr_attr->value.filter_query_method;
535 break;
536 case BT_COMPONENT_CLASS_TYPE_SINK:
537 cc_full_descr->methods.sink.query =
538 cur_cc_descr_attr->value.sink_query_method;
539 break;
540 default:
541 abort();
542 }
543 break;
544 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_INPUT_PORT_CONNECTION_METHOD:
545 switch (cc_type) {
546 case BT_COMPONENT_CLASS_TYPE_FILTER:
547 cc_full_descr->methods.filter.accept_input_port_connection =
548 cur_cc_descr_attr->value.filter_accept_input_port_connection_method;
549 break;
550 case BT_COMPONENT_CLASS_TYPE_SINK:
551 cc_full_descr->methods.sink.accept_input_port_connection =
552 cur_cc_descr_attr->value.sink_accept_input_port_connection_method;
553 break;
554 default:
555 abort();
556 }
557 break;
558 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_OUTPUT_PORT_CONNECTION_METHOD:
559 switch (cc_type) {
560 case BT_COMPONENT_CLASS_TYPE_SOURCE:
561 cc_full_descr->methods.source.accept_output_port_connection =
562 cur_cc_descr_attr->value.source_accept_output_port_connection_method;
563 break;
564 case BT_COMPONENT_CLASS_TYPE_FILTER:
565 cc_full_descr->methods.filter.accept_output_port_connection =
566 cur_cc_descr_attr->value.filter_accept_output_port_connection_method;
567 break;
568 default:
569 abort();
570 }
571 break;
572 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INPUT_PORT_CONNECTED_METHOD:
573 switch (cc_type) {
574 case BT_COMPONENT_CLASS_TYPE_FILTER:
575 cc_full_descr->methods.filter.input_port_connected =
576 cur_cc_descr_attr->value.filter_input_port_connected_method;
577 break;
578 case BT_COMPONENT_CLASS_TYPE_SINK:
579 cc_full_descr->methods.sink.input_port_connected =
580 cur_cc_descr_attr->value.sink_input_port_connected_method;
581 break;
582 default:
583 abort();
584 }
585 break;
586 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_OUTPUT_PORT_CONNECTED_METHOD:
587 switch (cc_type) {
588 case BT_COMPONENT_CLASS_TYPE_SOURCE:
589 cc_full_descr->methods.source.output_port_connected =
590 cur_cc_descr_attr->value.source_output_port_connected_method;
591 break;
592 case BT_COMPONENT_CLASS_TYPE_FILTER:
593 cc_full_descr->methods.filter.output_port_connected =
594 cur_cc_descr_attr->value.filter_output_port_connected_method;
595 break;
596 default:
597 abort();
598 }
599 break;
600 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GRAPH_IS_CONFIGURED_METHOD:
601 switch (cc_type) {
602 case BT_COMPONENT_CLASS_TYPE_SINK:
603 cc_full_descr->methods.sink.graph_is_configured =
604 cur_cc_descr_attr->value.sink_graph_is_configured_method;
605 break;
606 default:
607 abort();
608 }
609 break;
610 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_INIT_METHOD:
611 switch (cc_type) {
612 case BT_COMPONENT_CLASS_TYPE_SOURCE:
613 cc_full_descr->methods.source.msg_iter_init =
614 cur_cc_descr_attr->value.source_msg_iter_init_method;
615 break;
616 case BT_COMPONENT_CLASS_TYPE_FILTER:
617 cc_full_descr->methods.filter.msg_iter_init =
618 cur_cc_descr_attr->value.filter_msg_iter_init_method;
619 break;
620 default:
621 abort();
622 }
623 break;
624 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_FINALIZE_METHOD:
625 switch (cc_type) {
626 case BT_COMPONENT_CLASS_TYPE_SOURCE:
627 cc_full_descr->methods.source.msg_iter_finalize =
628 cur_cc_descr_attr->value.source_msg_iter_finalize_method;
629 break;
630 case BT_COMPONENT_CLASS_TYPE_FILTER:
631 cc_full_descr->methods.filter.msg_iter_finalize =
632 cur_cc_descr_attr->value.filter_msg_iter_finalize_method;
633 break;
634 default:
635 abort();
636 }
637 break;
638 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_NS_FROM_ORIGIN_METHOD:
639 switch (cc_type) {
640 case BT_COMPONENT_CLASS_TYPE_SOURCE:
641 cc_full_descr->methods.source.msg_iter_seek_ns_from_origin =
642 cur_cc_descr_attr->value.source_msg_iter_seek_ns_from_origin_method;
643 break;
644 case BT_COMPONENT_CLASS_TYPE_FILTER:
645 cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin =
646 cur_cc_descr_attr->value.filter_msg_iter_seek_ns_from_origin_method;
647 break;
648 default:
649 abort();
650 }
651 break;
652 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_BEGINNING_METHOD:
653 switch (cc_type) {
654 case BT_COMPONENT_CLASS_TYPE_SOURCE:
655 cc_full_descr->methods.source.msg_iter_seek_beginning =
656 cur_cc_descr_attr->value.source_msg_iter_seek_beginning_method;
657 break;
658 case BT_COMPONENT_CLASS_TYPE_FILTER:
659 cc_full_descr->methods.filter.msg_iter_seek_beginning =
660 cur_cc_descr_attr->value.filter_msg_iter_seek_beginning_method;
661 break;
662 default:
663 abort();
664 }
665 break;
666 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_NS_FROM_ORIGIN_METHOD:
667 switch (cc_type) {
668 case BT_COMPONENT_CLASS_TYPE_SOURCE:
669 cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin =
670 cur_cc_descr_attr->value.source_msg_iter_can_seek_ns_from_origin_method;
671 break;
672 case BT_COMPONENT_CLASS_TYPE_FILTER:
673 cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin =
674 cur_cc_descr_attr->value.filter_msg_iter_can_seek_ns_from_origin_method;
675 break;
676 default:
677 abort();
678 }
679 break;
680 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_BEGINNING_METHOD:
681 switch (cc_type) {
682 case BT_COMPONENT_CLASS_TYPE_SOURCE:
683 cc_full_descr->methods.source.msg_iter_can_seek_beginning =
684 cur_cc_descr_attr->value.source_msg_iter_can_seek_beginning_method;
685 break;
686 case BT_COMPONENT_CLASS_TYPE_FILTER:
687 cc_full_descr->methods.filter.msg_iter_can_seek_beginning =
688 cur_cc_descr_attr->value.filter_msg_iter_can_seek_beginning_method;
689 break;
690 default:
691 abort();
692 }
693 break;
694 default:
695 /*
696 * WARN-level logging because this
697 * should not happen with the
698 * appropriate ABI version. If we're
699 * here, we know that for the reported
700 * version of the ABI, this attribute is
701 * unknown.
702 */
703 BT_LOGW("Ignoring unknown component class descriptor attribute: "
704 "plugin-path=\"%s\", "
705 "plugin-name=\"%s\", "
706 "comp-class-name=\"%s\", "
707 "comp-class-type=%s, "
708 "attr-type-name=\"%s\", "
709 "attr-type-id=%d",
710 spec->shared_lib_handle->path ?
711 spec->shared_lib_handle->path->str :
712 NULL,
713 descriptor->name,
714 cur_cc_descr_attr->comp_class_descriptor->name,
715 bt_component_class_type_string(
716 cur_cc_descr_attr->comp_class_descriptor->type),
717 cur_cc_descr_attr->type_name,
718 cur_cc_descr_attr->type);
719 break;
720 }
721 }
722 }
723
724 /* Initialize plugin */
725 if (spec->init) {
726 enum bt_self_plugin_status init_status;
727
728 BT_LOGD_STR("Calling user's plugin initialization function.");
729 init_status = spec->init((void *) plugin);
730 BT_LOGD("User function returned: %s",
731 bt_self_plugin_status_string(init_status));
732
733 if (init_status < 0) {
734 BT_LOGW_STR("User's plugin initialization function failed.");
735 status = BT_PLUGIN_STATUS_ERROR;
736 goto end;
737 }
738 }
739
740 spec->shared_lib_handle->init_called = BT_TRUE;
741
742 /* Add described component classes to plugin */
743 for (i = 0; i < comp_class_full_descriptors->len; i++) {
744 struct comp_class_full_descriptor *cc_full_descr =
745 &g_array_index(comp_class_full_descriptors,
746 struct comp_class_full_descriptor, i);
747 struct bt_component_class *comp_class = NULL;
748 struct bt_component_class_source *src_comp_class = NULL;
749 struct bt_component_class_filter *flt_comp_class = NULL;
750 struct bt_component_class_sink *sink_comp_class = NULL;
751
752 BT_LOGD("Creating and setting properties of plugin's component class: "
753 "plugin-path=\"%s\", plugin-name=\"%s\", "
754 "comp-class-name=\"%s\", comp-class-type=%s",
755 spec->shared_lib_handle->path ?
756 spec->shared_lib_handle->path->str :
757 NULL,
758 descriptor->name,
759 cc_full_descr->descriptor->name,
760 bt_component_class_type_string(
761 cc_full_descr->descriptor->type));
762
763 switch (cc_full_descr->descriptor->type) {
764 case BT_COMPONENT_CLASS_TYPE_SOURCE:
765 src_comp_class = bt_component_class_source_create(
766 cc_full_descr->descriptor->name,
767 cc_full_descr->descriptor->methods.source.msg_iter_next);
768 comp_class = bt_component_class_source_as_component_class(
769 src_comp_class);
770 break;
771 case BT_COMPONENT_CLASS_TYPE_FILTER:
772 flt_comp_class = bt_component_class_filter_create(
773 cc_full_descr->descriptor->name,
774 cc_full_descr->descriptor->methods.source.msg_iter_next);
775 comp_class = bt_component_class_filter_as_component_class(
776 flt_comp_class);
777 break;
778 case BT_COMPONENT_CLASS_TYPE_SINK:
779 sink_comp_class = bt_component_class_sink_create(
780 cc_full_descr->descriptor->name,
781 cc_full_descr->descriptor->methods.sink.consume);
782 comp_class = bt_component_class_sink_as_component_class(
783 sink_comp_class);
784 break;
785 default:
786 /*
787 * WARN-level logging because this should not
788 * happen with the appropriate ABI version. If
789 * we're here, we know that for the reported
790 * version of the ABI, this component class type
791 * is unknown.
792 */
793 BT_LOGW("Ignoring unknown component class type: "
794 "plugin-path=\"%s\", plugin-name=\"%s\", "
795 "comp-class-name=\"%s\", comp-class-type=%d",
796 spec->shared_lib_handle->path->str ?
797 spec->shared_lib_handle->path->str :
798 NULL,
799 descriptor->name,
800 cc_full_descr->descriptor->name,
801 cc_full_descr->descriptor->type);
802 continue;
803 }
804
805 if (!comp_class) {
806 BT_LOGE_STR("Cannot create component class.");
807 status = BT_PLUGIN_STATUS_ERROR;
808 goto end;
809 }
810
811 if (cc_full_descr->description) {
812 ret = bt_component_class_set_description(
813 comp_class, cc_full_descr->description);
814 if (ret) {
815 BT_LOGE_STR("Cannot set component class's description.");
816 status = BT_PLUGIN_STATUS_ERROR;
817 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
818 goto end;
819 }
820 }
821
822 if (cc_full_descr->help) {
823 ret = bt_component_class_set_help(comp_class,
824 cc_full_descr->help);
825 if (ret) {
826 BT_LOGE_STR("Cannot set component class's help string.");
827 status = BT_PLUGIN_STATUS_ERROR;
828 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
829 goto end;
830 }
831 }
832
833 switch (cc_full_descr->descriptor->type) {
834 case BT_COMPONENT_CLASS_TYPE_SOURCE:
835 if (cc_full_descr->methods.source.init) {
836 ret = bt_component_class_source_set_init_method(
837 src_comp_class,
838 cc_full_descr->methods.source.init);
839 if (ret) {
840 BT_LOGE_STR("Cannot set source component class's initialization method.");
841 status = BT_PLUGIN_STATUS_ERROR;
842 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
843 goto end;
844 }
845 }
846
847 if (cc_full_descr->methods.source.finalize) {
848 ret = bt_component_class_source_set_finalize_method(
849 src_comp_class,
850 cc_full_descr->methods.source.finalize);
851 if (ret) {
852 BT_LOGE_STR("Cannot set source component class's finalization method.");
853 status = BT_PLUGIN_STATUS_ERROR;
854 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
855 goto end;
856 }
857 }
858
859 if (cc_full_descr->methods.source.query) {
860 ret = bt_component_class_source_set_query_method(
861 src_comp_class,
862 cc_full_descr->methods.source.query);
863 if (ret) {
864 BT_LOGE_STR("Cannot set source component class's query method.");
865 status = BT_PLUGIN_STATUS_ERROR;
866 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
867 goto end;
868 }
869 }
870
871 if (cc_full_descr->methods.source.accept_output_port_connection) {
872 ret = bt_component_class_source_set_accept_output_port_connection_method(
873 src_comp_class,
874 cc_full_descr->methods.source.accept_output_port_connection);
875 if (ret) {
876 BT_LOGE_STR("Cannot set source component class's \"accept input output connection\" method.");
877 status = BT_PLUGIN_STATUS_ERROR;
878 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
879 goto end;
880 }
881 }
882
883 if (cc_full_descr->methods.source.output_port_connected) {
884 ret = bt_component_class_source_set_output_port_connected_method(
885 src_comp_class,
886 cc_full_descr->methods.source.output_port_connected);
887 if (ret) {
888 BT_LOGE_STR("Cannot set source component class's \"output port connected\" method.");
889 status = BT_PLUGIN_STATUS_ERROR;
890 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
891 goto end;
892 }
893 }
894
895 if (cc_full_descr->methods.source.msg_iter_init) {
896 ret = bt_component_class_source_set_message_iterator_init_method(
897 src_comp_class,
898 cc_full_descr->methods.source.msg_iter_init);
899 if (ret) {
900 BT_LOGE_STR("Cannot set source component class's message iterator initialization method.");
901 status = BT_PLUGIN_STATUS_ERROR;
902 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
903 goto end;
904 }
905 }
906
907 if (cc_full_descr->methods.source.msg_iter_finalize) {
908 ret = bt_component_class_source_set_message_iterator_finalize_method(
909 src_comp_class,
910 cc_full_descr->methods.source.msg_iter_finalize);
911 if (ret) {
912 BT_LOGE_STR("Cannot set source component class's message iterator finalization method.");
913 status = BT_PLUGIN_STATUS_ERROR;
914 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
915 goto end;
916 }
917 }
918
919 if (cc_full_descr->methods.source.msg_iter_seek_ns_from_origin) {
920 ret = bt_component_class_source_set_message_iterator_seek_ns_from_origin_method(
921 src_comp_class,
922 cc_full_descr->methods.source.msg_iter_seek_ns_from_origin);
923 if (ret) {
924 BT_LOGE_STR("Cannot set source component class's message iterator \"seek nanoseconds from origin\" method.");
925 status = BT_PLUGIN_STATUS_ERROR;
926 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
927 goto end;
928 }
929 }
930
931 if (cc_full_descr->methods.source.msg_iter_seek_beginning) {
932 ret = bt_component_class_source_set_message_iterator_seek_beginning_method(
933 src_comp_class,
934 cc_full_descr->methods.source.msg_iter_seek_beginning);
935 if (ret) {
936 BT_LOGE_STR("Cannot set source component class's message iterator \"seek beginning\" method.");
937 status = BT_PLUGIN_STATUS_ERROR;
938 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
939 goto end;
940 }
941 }
942
943 if (cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin) {
944 ret = bt_component_class_source_set_message_iterator_can_seek_ns_from_origin_method(
945 src_comp_class,
946 cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin);
947 if (ret) {
948 BT_LOGE_STR("Cannot set source component class's message iterator \"can seek nanoseconds from origin\" method.");
949 status = BT_PLUGIN_STATUS_ERROR;
950 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
951 goto end;
952 }
953 }
954
955 if (cc_full_descr->methods.source.msg_iter_can_seek_beginning) {
956 ret = bt_component_class_source_set_message_iterator_can_seek_beginning_method(
957 src_comp_class,
958 cc_full_descr->methods.source.msg_iter_can_seek_beginning);
959 if (ret) {
960 BT_LOGE_STR("Cannot set source component class's message iterator \"can seek beginning\" method.");
961 status = BT_PLUGIN_STATUS_ERROR;
962 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
963 goto end;
964 }
965 }
966
967 break;
968 case BT_COMPONENT_CLASS_TYPE_FILTER:
969 if (cc_full_descr->methods.filter.init) {
970 ret = bt_component_class_filter_set_init_method(
971 flt_comp_class,
972 cc_full_descr->methods.filter.init);
973 if (ret) {
974 BT_LOGE_STR("Cannot set filter component class's initialization method.");
975 status = BT_PLUGIN_STATUS_ERROR;
976 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
977 goto end;
978 }
979 }
980
981 if (cc_full_descr->methods.filter.finalize) {
982 ret = bt_component_class_filter_set_finalize_method(
983 flt_comp_class,
984 cc_full_descr->methods.filter.finalize);
985 if (ret) {
986 BT_LOGE_STR("Cannot set filter component class's finalization method.");
987 status = BT_PLUGIN_STATUS_ERROR;
988 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
989 goto end;
990 }
991 }
992
993 if (cc_full_descr->methods.filter.query) {
994 ret = bt_component_class_filter_set_query_method(
995 flt_comp_class,
996 cc_full_descr->methods.filter.query);
997 if (ret) {
998 BT_LOGE_STR("Cannot set filter component class's query method.");
999 status = BT_PLUGIN_STATUS_ERROR;
1000 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1001 goto end;
1002 }
1003 }
1004
1005 if (cc_full_descr->methods.filter.accept_input_port_connection) {
1006 ret = bt_component_class_filter_set_accept_input_port_connection_method(
1007 flt_comp_class,
1008 cc_full_descr->methods.filter.accept_input_port_connection);
1009 if (ret) {
1010 BT_LOGE_STR("Cannot set filter component class's \"accept input port connection\" method.");
1011 status = BT_PLUGIN_STATUS_ERROR;
1012 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1013 goto end;
1014 }
1015 }
1016
1017 if (cc_full_descr->methods.filter.accept_output_port_connection) {
1018 ret = bt_component_class_filter_set_accept_output_port_connection_method(
1019 flt_comp_class,
1020 cc_full_descr->methods.filter.accept_output_port_connection);
1021 if (ret) {
1022 BT_LOGE_STR("Cannot set filter component class's \"accept input output connection\" method.");
1023 status = BT_PLUGIN_STATUS_ERROR;
1024 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1025 goto end;
1026 }
1027 }
1028
1029 if (cc_full_descr->methods.filter.input_port_connected) {
1030 ret = bt_component_class_filter_set_input_port_connected_method(
1031 flt_comp_class,
1032 cc_full_descr->methods.filter.input_port_connected);
1033 if (ret) {
1034 BT_LOGE_STR("Cannot set filter component class's \"input port connected\" method.");
1035 status = BT_PLUGIN_STATUS_ERROR;
1036 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1037 goto end;
1038 }
1039 }
1040
1041 if (cc_full_descr->methods.filter.output_port_connected) {
1042 ret = bt_component_class_filter_set_output_port_connected_method(
1043 flt_comp_class,
1044 cc_full_descr->methods.filter.output_port_connected);
1045 if (ret) {
1046 BT_LOGE_STR("Cannot set filter component class's \"output port connected\" method.");
1047 status = BT_PLUGIN_STATUS_ERROR;
1048 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1049 goto end;
1050 }
1051 }
1052
1053 if (cc_full_descr->methods.filter.msg_iter_init) {
1054 ret = bt_component_class_filter_set_message_iterator_init_method(
1055 flt_comp_class,
1056 cc_full_descr->methods.filter.msg_iter_init);
1057 if (ret) {
1058 BT_LOGE_STR("Cannot set filter component class's message iterator initialization method.");
1059 status = BT_PLUGIN_STATUS_ERROR;
1060 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1061 goto end;
1062 }
1063 }
1064
1065 if (cc_full_descr->methods.filter.msg_iter_finalize) {
1066 ret = bt_component_class_filter_set_message_iterator_finalize_method(
1067 flt_comp_class,
1068 cc_full_descr->methods.filter.msg_iter_finalize);
1069 if (ret) {
1070 BT_LOGE_STR("Cannot set filter component class's message iterator finalization method.");
1071 status = BT_PLUGIN_STATUS_ERROR;
1072 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1073 goto end;
1074 }
1075 }
1076
1077 if (cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin) {
1078 ret = bt_component_class_filter_set_message_iterator_seek_ns_from_origin_method(
1079 flt_comp_class,
1080 cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin);
1081 if (ret) {
1082 BT_LOGE_STR("Cannot set filter component class's message iterator \"seek nanoseconds from origin\" method.");
1083 status = BT_PLUGIN_STATUS_ERROR;
1084 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1085 goto end;
1086 }
1087 }
1088
1089 if (cc_full_descr->methods.filter.msg_iter_seek_beginning) {
1090 ret = bt_component_class_filter_set_message_iterator_seek_beginning_method(
1091 flt_comp_class,
1092 cc_full_descr->methods.filter.msg_iter_seek_beginning);
1093 if (ret) {
1094 BT_LOGE_STR("Cannot set filter component class's message iterator \"seek beginning\" method.");
1095 status = BT_PLUGIN_STATUS_ERROR;
1096 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1097 goto end;
1098 }
1099 }
1100
1101 if (cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin) {
1102 ret = bt_component_class_filter_set_message_iterator_can_seek_ns_from_origin_method(
1103 flt_comp_class,
1104 cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin);
1105 if (ret) {
1106 BT_LOGE_STR("Cannot set filter component class's message iterator \"can seek nanoseconds from origin\" method.");
1107 status = BT_PLUGIN_STATUS_ERROR;
1108 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1109 goto end;
1110 }
1111 }
1112
1113 if (cc_full_descr->methods.filter.msg_iter_can_seek_beginning) {
1114 ret = bt_component_class_filter_set_message_iterator_can_seek_beginning_method(
1115 flt_comp_class,
1116 cc_full_descr->methods.filter.msg_iter_can_seek_beginning);
1117 if (ret) {
1118 BT_LOGE_STR("Cannot set filter component class's message iterator \"can seek beginning\" method.");
1119 status = BT_PLUGIN_STATUS_ERROR;
1120 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1121 goto end;
1122 }
1123 }
1124
1125 break;
1126 case BT_COMPONENT_CLASS_TYPE_SINK:
1127 if (cc_full_descr->methods.sink.init) {
1128 ret = bt_component_class_sink_set_init_method(
1129 sink_comp_class,
1130 cc_full_descr->methods.sink.init);
1131 if (ret) {
1132 BT_LOGE_STR("Cannot set sink component class's initialization method.");
1133 status = BT_PLUGIN_STATUS_ERROR;
1134 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1135 goto end;
1136 }
1137 }
1138
1139 if (cc_full_descr->methods.sink.finalize) {
1140 ret = bt_component_class_sink_set_finalize_method(
1141 sink_comp_class,
1142 cc_full_descr->methods.sink.finalize);
1143 if (ret) {
1144 BT_LOGE_STR("Cannot set sink component class's finalization method.");
1145 status = BT_PLUGIN_STATUS_ERROR;
1146 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1147 goto end;
1148 }
1149 }
1150
1151 if (cc_full_descr->methods.sink.query) {
1152 ret = bt_component_class_sink_set_query_method(
1153 sink_comp_class,
1154 cc_full_descr->methods.sink.query);
1155 if (ret) {
1156 BT_LOGE_STR("Cannot set sink component class's query method.");
1157 status = BT_PLUGIN_STATUS_ERROR;
1158 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1159 goto end;
1160 }
1161 }
1162
1163 if (cc_full_descr->methods.sink.accept_input_port_connection) {
1164 ret = bt_component_class_sink_set_accept_input_port_connection_method(
1165 sink_comp_class,
1166 cc_full_descr->methods.sink.accept_input_port_connection);
1167 if (ret) {
1168 BT_LOGE_STR("Cannot set sink component class's \"accept input port connection\" method.");
1169 status = BT_PLUGIN_STATUS_ERROR;
1170 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1171 goto end;
1172 }
1173 }
1174
1175 if (cc_full_descr->methods.sink.input_port_connected) {
1176 ret = bt_component_class_sink_set_input_port_connected_method(
1177 sink_comp_class,
1178 cc_full_descr->methods.sink.input_port_connected);
1179 if (ret) {
1180 BT_LOGE_STR("Cannot set sink component class's \"input port connected\" method.");
1181 status = BT_PLUGIN_STATUS_ERROR;
1182 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1183 goto end;
1184 }
1185 }
1186
1187 if (cc_full_descr->methods.sink.graph_is_configured) {
1188 ret = bt_component_class_sink_set_graph_is_configured_method(
1189 sink_comp_class,
1190 cc_full_descr->methods.sink.graph_is_configured);
1191 if (ret) {
1192 BT_LOGE_STR("Cannot set sink component class's \"graph is configured\" method.");
1193 status = BT_PLUGIN_STATUS_ERROR;
1194 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1195 goto end;
1196 }
1197 }
1198
1199 break;
1200 default:
1201 abort();
1202 }
1203
1204 /*
1205 * Add component class to the plugin object.
1206 *
1207 * This will call back
1208 * bt_plugin_so_on_add_component_class() so that we can
1209 * add a mapping in the component class list when we
1210 * know the component class is successfully added.
1211 */
1212 status = bt_plugin_add_component_class(plugin,
1213 (void *) comp_class);
1214 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
1215 if (status < 0) {
1216 BT_LOGE("Cannot add component class to plugin.");
1217 goto end;
1218 }
1219 }
1220
1221 end:
1222 g_array_free(comp_class_full_descriptors, TRUE);
1223 return status;
1224 }
1225
1226 static
1227 struct bt_plugin *bt_plugin_so_create_empty(
1228 struct bt_plugin_so_shared_lib_handle *shared_lib_handle)
1229 {
1230 struct bt_plugin *plugin;
1231 struct bt_plugin_so_spec_data *spec;
1232
1233 plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_SO);
1234 if (!plugin) {
1235 goto error;
1236 }
1237
1238 plugin->destroy_spec_data = bt_plugin_so_destroy_spec_data;
1239 plugin->spec_data = g_new0(struct bt_plugin_so_spec_data, 1);
1240 if (!plugin->spec_data) {
1241 BT_LOGE_STR("Failed to allocate one SO plugin specific data structure.");
1242 goto error;
1243 }
1244
1245 spec = plugin->spec_data;
1246 spec->shared_lib_handle = shared_lib_handle;
1247 bt_object_get_no_null_check(spec->shared_lib_handle);
1248 goto end;
1249
1250 error:
1251 BT_OBJECT_PUT_REF_AND_RESET(plugin);
1252
1253 end:
1254 return plugin;
1255 }
1256
1257 static
1258 size_t count_non_null_items_in_section(const void *begin, const void *end)
1259 {
1260 size_t count = 0;
1261 const int * const *begin_int = (const int * const *) begin;
1262 const int * const *end_int = (const int * const *) end;
1263 const int * const *iter;
1264
1265 for (iter = begin_int; iter != end_int; iter++) {
1266 if (*iter) {
1267 count++;
1268 }
1269 }
1270
1271 return count;
1272 }
1273
1274 static
1275 struct bt_plugin_set *bt_plugin_so_create_all_from_sections(
1276 struct bt_plugin_so_shared_lib_handle *shared_lib_handle,
1277 struct __bt_plugin_descriptor const * const *descriptors_begin,
1278 struct __bt_plugin_descriptor const * const *descriptors_end,
1279 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
1280 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
1281 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
1282 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
1283 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
1284 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
1285 {
1286 size_t descriptor_count;
1287 size_t attrs_count;
1288 size_t cc_descriptors_count;
1289 size_t cc_descr_attrs_count;
1290 size_t i;
1291 struct bt_plugin_set *plugin_set = NULL;
1292
1293 descriptor_count = count_non_null_items_in_section(descriptors_begin, descriptors_end);
1294 attrs_count = count_non_null_items_in_section(attrs_begin, attrs_end);
1295 cc_descriptors_count = count_non_null_items_in_section(cc_descriptors_begin, cc_descriptors_end);
1296 cc_descr_attrs_count = count_non_null_items_in_section(cc_descr_attrs_begin, cc_descr_attrs_end);
1297
1298 BT_LOGD("Creating all SO plugins from sections: "
1299 "plugin-path=\"%s\", "
1300 "descr-begin-addr=%p, descr-end-addr=%p, "
1301 "attrs-begin-addr=%p, attrs-end-addr=%p, "
1302 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
1303 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p, "
1304 "descr-count=%zu, attrs-count=%zu, "
1305 "cc-descr-count=%zu, cc-descr-attrs-count=%zu",
1306 shared_lib_handle->path ? shared_lib_handle->path->str : NULL,
1307 descriptors_begin, descriptors_end,
1308 attrs_begin, attrs_end,
1309 cc_descriptors_begin, cc_descriptors_end,
1310 cc_descr_attrs_begin, cc_descr_attrs_end,
1311 descriptor_count, attrs_count,
1312 cc_descriptors_count, cc_descr_attrs_count);
1313 plugin_set = bt_plugin_set_create();
1314 if (!plugin_set) {
1315 BT_LOGE_STR("Cannot create empty plugin set.");
1316 goto error;
1317 }
1318
1319 for (i = 0; i < descriptors_end - descriptors_begin; i++) {
1320 enum bt_plugin_status status;
1321 const struct __bt_plugin_descriptor *descriptor =
1322 descriptors_begin[i];
1323 struct bt_plugin *plugin;
1324
1325 if (descriptor == NULL) {
1326 continue;
1327 }
1328
1329 BT_LOGD("Creating plugin object for plugin: "
1330 "name=\"%s\", abi-major=%d, abi-minor=%d",
1331 descriptor->name, descriptor->major, descriptor->minor);
1332
1333 if (descriptor->major > __BT_PLUGIN_VERSION_MAJOR) {
1334 /*
1335 * DEBUG-level logging because we're only
1336 * _trying_ to open this file as a compatible
1337 * Babeltrace plugin: if it's not, it's not an
1338 * error. And because this can be tried during
1339 * bt_plugin_find_all_from_dir(), it's not
1340 * even a warning.
1341 */
1342 BT_LOGD("Unknown ABI major version: abi-major=%d",
1343 descriptor->major);
1344 goto error;
1345 }
1346
1347 plugin = bt_plugin_so_create_empty(shared_lib_handle);
1348 if (!plugin) {
1349 BT_LOGE_STR("Cannot create empty shared library handle.");
1350 goto error;
1351 }
1352
1353 if (shared_lib_handle && shared_lib_handle->path) {
1354 bt_plugin_set_path(plugin, shared_lib_handle->path->str);
1355 }
1356
1357 status = bt_plugin_so_init(plugin, descriptor, attrs_begin,
1358 attrs_end, cc_descriptors_begin, cc_descriptors_end,
1359 cc_descr_attrs_begin, cc_descr_attrs_end);
1360 if (status < 0) {
1361 /*
1362 * DEBUG-level logging because we're only
1363 * _trying_ to open this file as a compatible
1364 * Babeltrace plugin: if it's not, it's not an
1365 * error. And because this can be tried during
1366 * bt_plugin_find_all_from_dir(), it's not
1367 * even a warning.
1368 */
1369 BT_LOGD_STR("Cannot initialize SO plugin object from sections.");
1370 BT_OBJECT_PUT_REF_AND_RESET(plugin);
1371 goto error;
1372 }
1373
1374 /* Add to plugin set */
1375 bt_plugin_set_add_plugin(plugin_set, plugin);
1376 bt_object_put_ref(plugin);
1377 }
1378
1379 goto end;
1380
1381 error:
1382 BT_OBJECT_PUT_REF_AND_RESET(plugin_set);
1383
1384 end:
1385 return plugin_set;
1386 }
1387
1388 BT_HIDDEN
1389 struct bt_plugin_set *bt_plugin_so_create_all_from_static(void)
1390 {
1391 struct bt_plugin_set *plugin_set = NULL;
1392 struct bt_plugin_so_shared_lib_handle *shared_lib_handle =
1393 bt_plugin_so_shared_lib_handle_create(NULL);
1394
1395 if (!shared_lib_handle) {
1396 goto end;
1397 }
1398
1399 BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
1400 plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
1401 __bt_get_begin_section_plugin_descriptors(),
1402 __bt_get_end_section_plugin_descriptors(),
1403 __bt_get_begin_section_plugin_descriptor_attributes(),
1404 __bt_get_end_section_plugin_descriptor_attributes(),
1405 __bt_get_begin_section_component_class_descriptors(),
1406 __bt_get_end_section_component_class_descriptors(),
1407 __bt_get_begin_section_component_class_descriptor_attributes(),
1408 __bt_get_end_section_component_class_descriptor_attributes());
1409
1410 end:
1411 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
1412
1413 return plugin_set;
1414 }
1415
1416 BT_HIDDEN
1417 struct bt_plugin_set *bt_plugin_so_create_all_from_file(const char *path)
1418 {
1419 size_t path_len;
1420 struct bt_plugin_set *plugin_set = NULL;
1421 struct __bt_plugin_descriptor const * const *descriptors_begin = NULL;
1422 struct __bt_plugin_descriptor const * const *descriptors_end = NULL;
1423 struct __bt_plugin_descriptor_attribute const * const *attrs_begin = NULL;
1424 struct __bt_plugin_descriptor_attribute const * const *attrs_end = NULL;
1425 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin = NULL;
1426 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end = NULL;
1427 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin = NULL;
1428 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end = NULL;
1429 struct __bt_plugin_descriptor const * const *(*get_begin_section_plugin_descriptors)(void);
1430 struct __bt_plugin_descriptor const * const *(*get_end_section_plugin_descriptors)(void);
1431 struct __bt_plugin_descriptor_attribute const * const *(*get_begin_section_plugin_descriptor_attributes)(void);
1432 struct __bt_plugin_descriptor_attribute const * const *(*get_end_section_plugin_descriptor_attributes)(void);
1433 struct __bt_plugin_component_class_descriptor const * const *(*get_begin_section_component_class_descriptors)(void);
1434 struct __bt_plugin_component_class_descriptor const * const *(*get_end_section_component_class_descriptors)(void);
1435 struct __bt_plugin_component_class_descriptor_attribute const * const *(*get_begin_section_component_class_descriptor_attributes)(void);
1436 struct __bt_plugin_component_class_descriptor_attribute const * const *(*get_end_section_component_class_descriptor_attributes)(void);
1437 bt_bool is_libtool_wrapper = BT_FALSE, is_shared_object = BT_FALSE;
1438 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
1439
1440 if (!path) {
1441 BT_LOGW_STR("Invalid parameter: path is NULL.");
1442 goto end;
1443 }
1444
1445 BT_LOGD("Creating all SO plugins from file: path=\"%s\"", path);
1446 path_len = strlen(path);
1447 if (path_len <= PLUGIN_SUFFIX_LEN) {
1448 BT_LOGW("Invalid parameter: path length is too short: "
1449 "path-length=%zu", path_len);
1450 goto end;
1451 }
1452
1453 path_len++;
1454 /*
1455 * Check if the file ends with a known plugin file type suffix (i.e. .so
1456 * or .la on Linux).
1457 */
1458 is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX,
1459 path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN,
1460 LIBTOOL_PLUGIN_SUFFIX_LEN);
1461 is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX,
1462 path + path_len - NATIVE_PLUGIN_SUFFIX_LEN,
1463 NATIVE_PLUGIN_SUFFIX_LEN);
1464 if (!is_shared_object && !is_libtool_wrapper) {
1465 /* Name indicates this is not a plugin file; not an error */
1466 BT_LOGV("File is not a SO plugin file: path=\"%s\"", path);
1467 goto end;
1468 }
1469
1470 shared_lib_handle = bt_plugin_so_shared_lib_handle_create(path);
1471 if (!shared_lib_handle) {
1472 BT_LOGD_STR("Cannot create shared library handle.");
1473 goto end;
1474 }
1475
1476 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_plugin_descriptors",
1477 (gpointer *) &get_begin_section_plugin_descriptors)) {
1478 descriptors_begin = get_begin_section_plugin_descriptors();
1479 } else {
1480 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1481 "symbol=\"%s\"", path,
1482 "__bt_get_begin_section_plugin_descriptors");
1483 goto end;
1484 }
1485
1486 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_plugin_descriptors",
1487 (gpointer *) &get_end_section_plugin_descriptors)) {
1488 descriptors_end = get_end_section_plugin_descriptors();
1489 } else {
1490 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1491 "symbol=\"%s\"", path,
1492 "__bt_get_end_section_plugin_descriptors");
1493 goto end;
1494 }
1495
1496 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_plugin_descriptor_attributes",
1497 (gpointer *) &get_begin_section_plugin_descriptor_attributes)) {
1498 attrs_begin = get_begin_section_plugin_descriptor_attributes();
1499 } else {
1500 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1501 "symbol=\"%s\"", path,
1502 "__bt_get_begin_section_plugin_descriptor_attributes");
1503 }
1504
1505 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_plugin_descriptor_attributes",
1506 (gpointer *) &get_end_section_plugin_descriptor_attributes)) {
1507 attrs_end = get_end_section_plugin_descriptor_attributes();
1508 } else {
1509 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1510 "symbol=\"%s\"", path,
1511 "__bt_get_end_section_plugin_descriptor_attributes");
1512 }
1513
1514 if ((!!attrs_begin - !!attrs_end) != 0) {
1515 BT_LOGD("Found section start or end symbol, but not both: "
1516 "path=\"%s\", symbol-start=\"%s\", "
1517 "symbol-end=\"%s\", symbol-start-addr=%p, "
1518 "symbol-end-addr=%p",
1519 path, "__bt_get_begin_section_plugin_descriptor_attributes",
1520 "__bt_get_end_section_plugin_descriptor_attributes",
1521 attrs_begin, attrs_end);
1522 goto end;
1523 }
1524
1525 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_component_class_descriptors",
1526 (gpointer *) &get_begin_section_component_class_descriptors)) {
1527 cc_descriptors_begin = get_begin_section_component_class_descriptors();
1528 } else {
1529 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1530 "symbol=\"%s\"", path,
1531 "__bt_get_begin_section_component_class_descriptors");
1532 }
1533
1534 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_component_class_descriptors",
1535 (gpointer *) &get_end_section_component_class_descriptors)) {
1536 cc_descriptors_end = get_end_section_component_class_descriptors();
1537 } else {
1538 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1539 "symbol=\"%s\"", path,
1540 "__bt_get_end_section_component_class_descriptors");
1541 }
1542
1543 if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) {
1544 BT_LOGD("Found section start or end symbol, but not both: "
1545 "path=\"%s\", symbol-start=\"%s\", "
1546 "symbol-end=\"%s\", symbol-start-addr=%p, "
1547 "symbol-end-addr=%p",
1548 path, "__bt_get_begin_section_component_class_descriptors",
1549 "__bt_get_end_section_component_class_descriptors",
1550 cc_descriptors_begin, cc_descriptors_end);
1551 goto end;
1552 }
1553
1554 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_component_class_descriptor_attributes",
1555 (gpointer *) &get_begin_section_component_class_descriptor_attributes)) {
1556 cc_descr_attrs_begin = get_begin_section_component_class_descriptor_attributes();
1557 } else {
1558 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1559 "symbol=\"%s\"", path,
1560 "__bt_get_begin_section_component_class_descriptor_attributes");
1561 }
1562
1563 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_component_class_descriptor_attributes",
1564 (gpointer *) &get_end_section_component_class_descriptor_attributes)) {
1565 cc_descr_attrs_end = get_end_section_component_class_descriptor_attributes();
1566 } else {
1567 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1568 "symbol=\"%s\"", path,
1569 "__bt_get_end_section_component_class_descriptor_attributes");
1570 }
1571
1572 if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) {
1573 BT_LOGD("Found section start or end symbol, but not both: "
1574 "path=\"%s\", symbol-start=\"%s\", "
1575 "symbol-end=\"%s\", symbol-start-addr=%p, "
1576 "symbol-end-addr=%p",
1577 path, "__bt_get_begin_section_component_class_descriptor_attributes",
1578 "__bt_get_end_section_component_class_descriptor_attributes",
1579 cc_descr_attrs_begin, cc_descr_attrs_end);
1580 goto end;
1581 }
1582
1583 /* Initialize plugin */
1584 BT_LOGD_STR("Initializing plugin object.");
1585 plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
1586 descriptors_begin, descriptors_end, attrs_begin, attrs_end,
1587 cc_descriptors_begin, cc_descriptors_end,
1588 cc_descr_attrs_begin, cc_descr_attrs_end);
1589
1590 end:
1591 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
1592 return plugin_set;
1593 }
1594
1595 static
1596 void plugin_comp_class_destroy_listener(struct bt_component_class *comp_class,
1597 void *data)
1598 {
1599 bt_list_del(&comp_class->node);
1600 BT_OBJECT_PUT_REF_AND_RESET(comp_class->so_handle);
1601 BT_LOGV("Component class destroyed: removed entry from list: "
1602 "comp-cls-addr=%p", comp_class);
1603 }
1604
1605 void bt_plugin_so_on_add_component_class(struct bt_plugin *plugin,
1606 struct bt_component_class *comp_class)
1607 {
1608 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
1609
1610 BT_ASSERT(plugin->spec_data);
1611 BT_ASSERT(plugin->type == BT_PLUGIN_TYPE_SO);
1612
1613 bt_list_add(&comp_class->node, &component_class_list);
1614 comp_class->so_handle = spec->shared_lib_handle;
1615 bt_object_get_no_null_check(comp_class->so_handle);
1616
1617 /* Add our custom destroy listener */
1618 bt_component_class_add_destroy_listener(comp_class,
1619 plugin_comp_class_destroy_listener, NULL);
1620 }
This page took 0.061805 seconds and 4 git commands to generate.