cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[babeltrace.git] / src / lib / plugin / plugin.h
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
5 * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 */
7
8 #ifndef BABELTRACE_PLUGIN_PLUGIN_INTERNAL_H
9 #define BABELTRACE_PLUGIN_PLUGIN_INTERNAL_H
10
11 #include "common/common.h"
12 #include "lib/graph/component-class.h"
13 #include <babeltrace2/plugin/plugin-loading.h>
14 #include <babeltrace2/plugin/plugin-dev.h>
15 #include "lib/object.h"
16 #include <babeltrace2/types.h>
17 #include "common/assert.h"
18 #include <glib.h>
19 #include <stdbool.h>
20
21 #include "plugin-so.h"
22 #include "lib/func-status.h"
23
24 /* Protection: this file uses BT_LIB_LOG*() macros directly */
25 #ifndef BT_LIB_LOG_SUPPORTED
26 # error Please include "lib/logging.h" before including this file.
27 #endif
28
29 enum bt_plugin_type {
30 BT_PLUGIN_TYPE_SO = 0,
31 BT_PLUGIN_TYPE_PYTHON = 1,
32 };
33
34 struct bt_plugin {
35 struct bt_object base;
36 enum bt_plugin_type type;
37
38 /* Arrays of `struct bt_component_class *` (owned by this) */
39 GPtrArray *src_comp_classes;
40 GPtrArray *flt_comp_classes;
41 GPtrArray *sink_comp_classes;
42
43 /* Info (owned by this) */
44 struct {
45 GString *path;
46 GString *name;
47 GString *author;
48 GString *license;
49 GString *description;
50 struct {
51 unsigned int major;
52 unsigned int minor;
53 unsigned int patch;
54 GString *extra;
55 } version;
56 bool path_set;
57 bool name_set;
58 bool author_set;
59 bool license_set;
60 bool description_set;
61 bool version_set;
62 } info;
63
64 /* Value depends on the specific plugin type */
65 void *spec_data;
66 void (*destroy_spec_data)(struct bt_plugin *);
67 };
68
69 struct bt_plugin_set {
70 struct bt_object base;
71
72 /* Array of struct bt_plugin * */
73 GPtrArray *plugins;
74 };
75
76 static inline
77 const char *bt_plugin_type_string(enum bt_plugin_type type)
78 {
79 switch (type) {
80 case BT_PLUGIN_TYPE_SO:
81 return "SO";
82 case BT_PLUGIN_TYPE_PYTHON:
83 return "PYTHON";
84 default:
85 return "(unknown)";
86 }
87 }
88
89 static inline
90 void bt_plugin_destroy(struct bt_object *obj)
91 {
92 struct bt_plugin *plugin;
93
94 BT_ASSERT(obj);
95 plugin = container_of(obj, struct bt_plugin, base);
96 BT_LIB_LOGI("Destroying plugin object: %!+l", plugin);
97
98 if (plugin->destroy_spec_data) {
99 plugin->destroy_spec_data(plugin);
100 }
101
102 if (plugin->src_comp_classes) {
103 BT_LOGD_STR("Putting source component classes.");
104 g_ptr_array_free(plugin->src_comp_classes, TRUE);
105 plugin->src_comp_classes = NULL;
106 }
107
108 if (plugin->flt_comp_classes) {
109 BT_LOGD_STR("Putting filter component classes.");
110 g_ptr_array_free(plugin->flt_comp_classes, TRUE);
111 plugin->flt_comp_classes = NULL;
112 }
113
114 if (plugin->sink_comp_classes) {
115 BT_LOGD_STR("Putting sink component classes.");
116 g_ptr_array_free(plugin->sink_comp_classes, TRUE);
117 plugin->sink_comp_classes = NULL;
118 }
119
120 if (plugin->info.name) {
121 g_string_free(plugin->info.name, TRUE);
122 plugin->info.name = NULL;
123 }
124
125 if (plugin->info.path) {
126 g_string_free(plugin->info.path, TRUE);
127 plugin->info.path = NULL;
128 }
129
130 if (plugin->info.description) {
131 g_string_free(plugin->info.description, TRUE);
132 plugin->info.description = NULL;
133 }
134
135 if (plugin->info.author) {
136 g_string_free(plugin->info.author, TRUE);
137 plugin->info.author = NULL;
138 }
139
140 if (plugin->info.license) {
141 g_string_free(plugin->info.license, TRUE);
142 plugin->info.license = NULL;
143 }
144
145 if (plugin->info.version.extra) {
146 g_string_free(plugin->info.version.extra, TRUE);
147 plugin->info.version.extra = NULL;
148 }
149
150 g_free(plugin);
151 }
152
153 static inline
154 struct bt_plugin *bt_plugin_create_empty(enum bt_plugin_type type)
155 {
156 struct bt_plugin *plugin = NULL;
157
158 BT_LOGD("Creating empty plugin object: type=%s",
159 bt_plugin_type_string(type));
160
161 plugin = g_new0(struct bt_plugin, 1);
162 if (!plugin) {
163 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one plugin.");
164 goto error;
165 }
166
167 bt_object_init_shared(&plugin->base, bt_plugin_destroy);
168 plugin->type = type;
169
170 /* Create empty arrays of component classes */
171 plugin->src_comp_classes =
172 g_ptr_array_new_with_free_func(
173 (GDestroyNotify) bt_object_put_ref);
174 if (!plugin->src_comp_classes) {
175 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GPtrArray.");
176 goto error;
177 }
178
179 plugin->flt_comp_classes =
180 g_ptr_array_new_with_free_func(
181 (GDestroyNotify) bt_object_put_ref);
182 if (!plugin->flt_comp_classes) {
183 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GPtrArray.");
184 goto error;
185 }
186
187 plugin->sink_comp_classes =
188 g_ptr_array_new_with_free_func(
189 (GDestroyNotify) bt_object_put_ref);
190 if (!plugin->sink_comp_classes) {
191 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GPtrArray.");
192 goto error;
193 }
194
195 /* Create empty info */
196 plugin->info.name = g_string_new(NULL);
197 if (!plugin->info.name) {
198 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
199 goto error;
200 }
201
202 plugin->info.path = g_string_new(NULL);
203 if (!plugin->info.path) {
204 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
205 goto error;
206 }
207
208 plugin->info.description = g_string_new(NULL);
209 if (!plugin->info.description) {
210 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
211 goto error;
212 }
213
214 plugin->info.author = g_string_new(NULL);
215 if (!plugin->info.author) {
216 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
217 goto error;
218 }
219
220 plugin->info.license = g_string_new(NULL);
221 if (!plugin->info.license) {
222 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
223 goto error;
224 }
225
226 plugin->info.version.extra = g_string_new(NULL);
227 if (!plugin->info.version.extra) {
228 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
229 goto error;
230 }
231
232 BT_LIB_LOGD("Created empty plugin object: %!+l", plugin);
233 goto end;
234
235 error:
236 BT_OBJECT_PUT_REF_AND_RESET(plugin);
237
238 end:
239 return plugin;
240 }
241
242 static inline
243 void bt_plugin_set_path(struct bt_plugin *plugin, const char *path)
244 {
245 BT_ASSERT(plugin);
246 BT_ASSERT(path);
247 g_string_assign(plugin->info.path, path);
248 plugin->info.path_set = BT_TRUE;
249 BT_LIB_LOGD("Set plugin's path: %![plugin-]+l, path=\"%s\"",
250 plugin, path);
251 }
252
253 static inline
254 void bt_plugin_set_name(struct bt_plugin *plugin, const char *name)
255 {
256 BT_ASSERT(plugin);
257 BT_ASSERT(name);
258 g_string_assign(plugin->info.name, name);
259 plugin->info.name_set = BT_TRUE;
260 BT_LIB_LOGD("Set plugin's name: %![plugin-]+l, name=\"%s\"",
261 plugin, name);
262 }
263
264 static inline
265 void bt_plugin_set_description(struct bt_plugin *plugin,
266 const char *description)
267 {
268 BT_ASSERT(plugin);
269 BT_ASSERT(description);
270 g_string_assign(plugin->info.description, description);
271 plugin->info.description_set = BT_TRUE;
272 BT_LIB_LOGD("Set plugin's description: %![plugin-]+l", plugin);
273 }
274
275 static inline
276 void bt_plugin_set_author(struct bt_plugin *plugin, const char *author)
277 {
278 BT_ASSERT(plugin);
279 BT_ASSERT(author);
280 g_string_assign(plugin->info.author, author);
281 plugin->info.author_set = BT_TRUE;
282 BT_LIB_LOGD("Set plugin's author: %![plugin-]+l, author=\"%s\"",
283 plugin, author);
284 }
285
286 static inline
287 void bt_plugin_set_license(struct bt_plugin *plugin, const char *license)
288 {
289 BT_ASSERT(plugin);
290 BT_ASSERT(license);
291 g_string_assign(plugin->info.license, license);
292 plugin->info.license_set = BT_TRUE;
293 BT_LIB_LOGD("Set plugin's path: %![plugin-]+l, license=\"%s\"",
294 plugin, license);
295 }
296
297 static inline
298 void bt_plugin_set_version(struct bt_plugin *plugin, unsigned int major,
299 unsigned int minor, unsigned int patch, const char *extra)
300 {
301 BT_ASSERT(plugin);
302 plugin->info.version.major = major;
303 plugin->info.version.minor = minor;
304 plugin->info.version.patch = patch;
305
306 if (extra) {
307 g_string_assign(plugin->info.version.extra, extra);
308 }
309
310 plugin->info.version_set = BT_TRUE;
311 BT_LIB_LOGD("Set plugin's version: %![plugin-]+l, "
312 "major=%u, minor=%u, patch=%u, extra=\"%s\"",
313 plugin, major, minor, patch, extra);
314 }
315
316 static inline
317 int bt_plugin_add_component_class(
318 struct bt_plugin *plugin, struct bt_component_class *comp_class)
319 {
320 GPtrArray *comp_classes;
321
322 BT_ASSERT(plugin);
323 BT_ASSERT(comp_class);
324
325 switch (comp_class->type) {
326 case BT_COMPONENT_CLASS_TYPE_SOURCE:
327 comp_classes = plugin->src_comp_classes;
328 break;
329 case BT_COMPONENT_CLASS_TYPE_FILTER:
330 comp_classes = plugin->flt_comp_classes;
331 break;
332 case BT_COMPONENT_CLASS_TYPE_SINK:
333 comp_classes = plugin->sink_comp_classes;
334 break;
335 default:
336 bt_common_abort();
337 }
338
339 /* Set component class's original plugin name */
340 BT_ASSERT(comp_class->plugin_name);
341 BT_ASSERT(plugin->info.name);
342 g_string_assign(comp_class->plugin_name, plugin->info.name->str);
343
344 /* Add new component class */
345 bt_object_get_ref(comp_class);
346 g_ptr_array_add(comp_classes, comp_class);
347
348 /* Special case for a shared object plugin */
349 if (plugin->type == BT_PLUGIN_TYPE_SO) {
350 bt_plugin_so_on_add_component_class(plugin, comp_class);
351 }
352
353 BT_LIB_LOGD("Added component class to plugin: "
354 "%![plugin-]+l, %![cc-]+C", plugin, comp_class);
355 return BT_FUNC_STATUS_OK;
356 }
357
358 static
359 void bt_plugin_set_destroy(struct bt_object *obj)
360 {
361 struct bt_plugin_set *plugin_set =
362 container_of(obj, struct bt_plugin_set, base);
363
364 if (!plugin_set) {
365 return;
366 }
367
368 BT_LOGD("Destroying plugin set: addr=%p", plugin_set);
369
370 if (plugin_set->plugins) {
371 BT_LOGD_STR("Putting plugins.");
372 g_ptr_array_free(plugin_set->plugins, TRUE);
373 }
374
375 g_free(plugin_set);
376 }
377
378 static inline
379 struct bt_plugin_set *bt_plugin_set_create(void)
380 {
381 struct bt_plugin_set *plugin_set = g_new0(struct bt_plugin_set, 1);
382
383 if (!plugin_set) {
384 goto end;
385 }
386
387 BT_LOGD_STR("Creating empty plugin set.");
388 bt_object_init_shared(&plugin_set->base, bt_plugin_set_destroy);
389
390 plugin_set->plugins = g_ptr_array_new_with_free_func(
391 (GDestroyNotify) bt_object_put_ref);
392 if (!plugin_set->plugins) {
393 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GPtrArray.");
394 BT_OBJECT_PUT_REF_AND_RESET(plugin_set);
395 goto end;
396 }
397
398 BT_LOGD("Created empty plugin set: addr=%p", plugin_set);
399
400 end:
401 return plugin_set;
402 }
403
404 static inline
405 bool bt_plugin_set_contains_plugin(struct bt_plugin_set *plugin_set,
406 const char *name)
407 {
408 uint64_t i;
409 bool contains = false;
410
411 BT_ASSERT(plugin_set);
412 BT_ASSERT(name);
413
414 for (i = 0; i < plugin_set->plugins->len; i++) {
415 const struct bt_plugin *plugin = plugin_set->plugins->pdata[i];
416
417 if (strcmp(plugin->info.name->str, name) == 0) {
418 contains = true;
419 goto end;
420 }
421 }
422
423 end:
424 return contains;
425 }
426
427 static inline
428 void bt_plugin_set_add_plugin(struct bt_plugin_set *plugin_set,
429 struct bt_plugin *plugin)
430 {
431 BT_ASSERT(plugin_set);
432 BT_ASSERT(plugin);
433
434 if (bt_plugin_set_contains_plugin(plugin_set,
435 plugin->info.name->str)) {
436 goto end;
437 }
438
439 bt_object_get_ref(plugin);
440 g_ptr_array_add(plugin_set->plugins, plugin);
441 BT_LIB_LOGD("Added plugin to plugin set: "
442 "plugin-set-addr=%p, %![plugin-]+l",
443 plugin_set, plugin);
444
445 end:
446 return;
447 }
448
449 #endif /* BABELTRACE_PLUGIN_PLUGIN_INTERNAL_H */
This page took 0.037734 seconds and 4 git commands to generate.