Implement the component graph interface
[babeltrace.git] / lib / component / component-class.c
CommitLineData
fb2dcc52
JG
1/*
2 * component-class.c
3 *
4 * Babeltrace Plugin Component Class
33b34c43 5 *
3310b217 6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
fb2dcc52
JG
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29#include <babeltrace/compiler.h>
33b34c43 30#include <babeltrace/component/component-class-internal.h>
b8a06801 31#include <babeltrace/ref.h>
1e4d8103 32#include <stdbool.h>
fb2dcc52
JG
33#include <glib.h>
34
35static
b8a06801 36void bt_component_class_destroy(struct bt_object *obj)
fb2dcc52
JG
37{
38 struct bt_component_class *class;
33b34c43 39 int i;
fb2dcc52 40
b8a06801
JG
41 assert(obj);
42 class = container_of(obj, struct bt_component_class, base);
33b34c43
PP
43
44 /* Call destroy listeners in reverse registration order */
45 for (i = class->destroy_listeners->len - 1; i >= 0; i--) {
d3e4dcd8 46 struct bt_component_class_destroy_listener *listener =
33b34c43 47 &g_array_index(class->destroy_listeners,
d3e4dcd8 48 struct bt_component_class_destroy_listener,
33b34c43
PP
49 i);
50
51 listener->func(class, listener->data);
52 }
53
fb2dcc52
JG
54 if (class->name) {
55 g_string_free(class->name, TRUE);
56 }
7c7c0433
JG
57 if (class->description) {
58 g_string_free(class->description, TRUE);
59 }
5536d9a6
PP
60 if (class->help) {
61 g_string_free(class->help, TRUE);
62 }
33b34c43
PP
63 if (class->destroy_listeners) {
64 g_array_free(class->destroy_listeners, TRUE);
65 }
b8a06801 66
fb2dcc52
JG
67 g_free(class);
68}
69
d3e4dcd8
PP
70static
71int bt_component_class_init(struct bt_component_class *class,
72 enum bt_component_class_type type, const char *name)
fb2dcc52 73{
d3e4dcd8
PP
74 int ret = 0;
75
76 bt_object_init(class, bt_component_class_destroy);
77 class->type = type;
78 class->name = g_string_new(name);
79 if (!class->name) {
80 goto error;
81 }
82
83 class->description = g_string_new(NULL);
84 if (!class->description) {
85 goto error;
86 }
87
5536d9a6
PP
88 class->help = g_string_new(NULL);
89 if (!class->help) {
90 goto error;
91 }
92
d3e4dcd8
PP
93 class->destroy_listeners = g_array_new(FALSE, TRUE,
94 sizeof(struct bt_component_class_destroy_listener));
95 if (!class->destroy_listeners) {
96 goto error;
97 }
98
99 goto end;
6ba0b073 100
d3e4dcd8
PP
101error:
102 BT_PUT(class);
103 ret = -1;
104
105end:
106 return ret;
107}
108
109struct bt_component_class *bt_component_class_source_create(const char *name,
d3eb6e8f
PP
110 bt_component_class_notification_iterator_get_method notification_iterator_get_method,
111 bt_component_class_notification_iterator_next_method notification_iterator_next_method)
d3e4dcd8
PP
112{
113 struct bt_component_class_source *source_class = NULL;
114 int ret;
115
d3eb6e8f
PP
116 if (!name || !notification_iterator_get_method ||
117 !notification_iterator_next_method) {
6ba0b073
PP
118 goto end;
119 }
fb2dcc52 120
d3e4dcd8
PP
121 source_class = g_new0(struct bt_component_class_source, 1);
122 if (!source_class) {
fb2dcc52
JG
123 goto end;
124 }
125
d3e4dcd8
PP
126 ret = bt_component_class_init(&source_class->parent,
127 BT_COMPONENT_CLASS_TYPE_SOURCE, name);
128 if (ret) {
129 /*
130 * If bt_component_class_init() fails, the component
131 * class is put, therefore its memory is already
132 * freed.
133 */
134 source_class = NULL;
135 goto end;
136 }
137
d3eb6e8f
PP
138 source_class->methods.iterator.get = notification_iterator_get_method;
139 source_class->methods.iterator.next = notification_iterator_next_method;
d3e4dcd8
PP
140
141end:
142 return &source_class->parent;
143}
144
145struct bt_component_class *bt_component_class_filter_create(const char *name,
d3eb6e8f
PP
146 bt_component_class_notification_iterator_get_method notification_iterator_get_method,
147 bt_component_class_notification_iterator_next_method notification_iterator_next_method)
d3e4dcd8
PP
148{
149 struct bt_component_class_filter *filter_class = NULL;
150 int ret;
151
d3eb6e8f
PP
152 if (!name || !notification_iterator_get_method ||
153 !notification_iterator_next_method) {
fb2dcc52
JG
154 goto end;
155 }
6ba0b073 156
d3e4dcd8
PP
157 filter_class = g_new0(struct bt_component_class_filter, 1);
158 if (!filter_class) {
159 goto end;
6ba0b073
PP
160 }
161
d3e4dcd8
PP
162 ret = bt_component_class_init(&filter_class->parent,
163 BT_COMPONENT_CLASS_TYPE_FILTER, name);
164 if (ret) {
165 /*
166 * If bt_component_class_init() fails, the component
167 * class is put, therefore its memory is already
168 * freed.
169 */
170 filter_class = NULL;
33b34c43
PP
171 goto end;
172 }
d3e4dcd8 173
d3eb6e8f
PP
174 filter_class->methods.iterator.get = notification_iterator_get_method;
175 filter_class->methods.iterator.next = notification_iterator_next_method;
d3e4dcd8 176
fb2dcc52 177end:
d3e4dcd8
PP
178 return &filter_class->parent;
179}
180
181struct bt_component_class *bt_component_class_sink_create(const char *name,
182 bt_component_class_sink_consume_method consume_method)
183{
184 struct bt_component_class_sink *sink_class = NULL;
185 int ret;
186
187 if (!name || !consume_method) {
188 goto end;
189 }
190
191 sink_class = g_new0(struct bt_component_class_sink, 1);
192 if (!sink_class) {
193 goto end;
194 }
195
196 ret = bt_component_class_init(&sink_class->parent,
197 BT_COMPONENT_CLASS_TYPE_SINK, name);
198 if (ret) {
199 /*
200 * If bt_component_class_init() fails, the component
201 * class is put, therefore its memory is already
202 * freed.
203 */
204 sink_class = NULL;
205 goto end;
206 }
207
208 sink_class->methods.consume = consume_method;
209
210end:
211 return &sink_class->parent;
212}
213
214int bt_component_class_set_init_method(
215 struct bt_component_class *component_class,
216 bt_component_class_init_method init_method)
217{
218 int ret = 0;
219
1e4d8103 220 if (!component_class || component_class->frozen || !init_method) {
d3e4dcd8
PP
221 ret = -1;
222 goto end;
223 }
224
225 component_class->methods.init = init_method;
226
227end:
228 return ret;
229}
230
a67681c1 231int bt_component_class_set_query_method(
efa96d5d 232 struct bt_component_class *component_class,
a67681c1 233 bt_component_class_query_method query_method)
efa96d5d
PP
234{
235 int ret = 0;
236
a67681c1 237 if (!component_class || component_class->frozen || !query_method) {
efa96d5d
PP
238 ret = -1;
239 goto end;
240 }
241
a67681c1 242 component_class->methods.query = query_method;
efa96d5d
PP
243
244end:
245 return ret;
246}
247
d3e4dcd8
PP
248int bt_component_class_set_destroy_method(
249 struct bt_component_class *component_class,
250 bt_component_class_destroy_method destroy_method)
251{
252 int ret = 0;
253
1e4d8103 254 if (!component_class || component_class->frozen || !destroy_method) {
d3e4dcd8
PP
255 ret = -1;
256 goto end;
257 }
258
259 component_class->methods.destroy = destroy_method;
260
261end:
262 return ret;
263}
264
d3eb6e8f
PP
265int bt_component_class_source_set_notification_iterator_init_method(
266 struct bt_component_class *component_class,
267 bt_component_class_notification_iterator_init_method notification_iterator_init_method)
268{
269 struct bt_component_class_source *source_class;
270 int ret = 0;
271
272 if (!component_class || component_class->frozen ||
273 !notification_iterator_init_method ||
274 component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
275 ret = -1;
276 goto end;
277 }
278
279 source_class = container_of(component_class,
280 struct bt_component_class_source, parent);
281 source_class->methods.iterator.init = notification_iterator_init_method;
282
283end:
284 return ret;
285}
286
287int bt_component_class_source_set_notification_iterator_destroy_method(
288 struct bt_component_class *component_class,
289 bt_component_class_notification_iterator_destroy_method notification_iterator_destroy_method)
290{
291 struct bt_component_class_source *source_class;
292 int ret = 0;
293
294 if (!component_class || component_class->frozen ||
295 !notification_iterator_destroy_method ||
296 component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
297 ret = -1;
298 goto end;
299 }
300
301 source_class = container_of(component_class,
302 struct bt_component_class_source, parent);
303 source_class->methods.iterator.destroy =
304 notification_iterator_destroy_method;
305
306end:
307 return ret;
308}
309
310int bt_component_class_source_set_notification_iterator_seek_time_method(
311 struct bt_component_class *component_class,
312 bt_component_class_notification_iterator_seek_time_method notification_iterator_seek_time_method)
313{
314 struct bt_component_class_source *source_class;
315 int ret = 0;
316
317 if (!component_class || component_class->frozen ||
318 !notification_iterator_seek_time_method ||
319 component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
320 ret = -1;
321 goto end;
322 }
323
324 source_class = container_of(component_class,
325 struct bt_component_class_source, parent);
326 source_class->methods.iterator.seek_time =
327 notification_iterator_seek_time_method;
328
329end:
330 return ret;
331}
332
333int bt_component_class_filter_set_notification_iterator_init_method(
334 struct bt_component_class *component_class,
335 bt_component_class_notification_iterator_init_method notification_iterator_init_method)
336{
337 struct bt_component_class_filter *filter_class;
338 int ret = 0;
339
340 if (!component_class || component_class->frozen ||
341 !notification_iterator_init_method ||
342 component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
343 ret = -1;
344 goto end;
345 }
346
347 filter_class = container_of(component_class,
348 struct bt_component_class_filter, parent);
349 filter_class->methods.iterator.init = notification_iterator_init_method;
350
351end:
352 return ret;
353}
354
355int bt_component_class_filter_set_notification_iterator_destroy_method(
356 struct bt_component_class *component_class,
357 bt_component_class_notification_iterator_destroy_method notification_iterator_destroy_method)
358{
359 struct bt_component_class_filter *filter_class;
360 int ret = 0;
361
362 if (!component_class || component_class->frozen ||
363 !notification_iterator_destroy_method ||
364 component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
365 ret = -1;
366 goto end;
367 }
368
369 filter_class = container_of(component_class,
370 struct bt_component_class_filter, parent);
371 filter_class->methods.iterator.destroy =
372 notification_iterator_destroy_method;
373
374end:
375 return ret;
376}
377
378int bt_component_class_filter_set_notification_iterator_seek_time_method(
379 struct bt_component_class *component_class,
380 bt_component_class_notification_iterator_seek_time_method notification_iterator_seek_time_method)
381{
382 struct bt_component_class_filter *filter_class;
383 int ret = 0;
384
385 if (!component_class || component_class->frozen ||
386 !notification_iterator_seek_time_method ||
387 component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
388 ret = -1;
389 goto end;
390 }
391
392 filter_class = container_of(component_class,
393 struct bt_component_class_filter, parent);
394 filter_class->methods.iterator.seek_time =
395 notification_iterator_seek_time_method;
396
397end:
398 return ret;
399}
400
401int bt_component_class_set_description(
d3e4dcd8
PP
402 struct bt_component_class *component_class,
403 const char *description)
404{
405 int ret = 0;
406
1e4d8103 407 if (!component_class || component_class->frozen || !description) {
d3e4dcd8
PP
408 ret = -1;
409 goto end;
410 }
411
412 g_string_assign(component_class->description, description);
413
414end:
415 return ret;
fb2dcc52 416}
38b48196 417
5536d9a6
PP
418int bt_component_class_set_help(
419 struct bt_component_class *component_class,
420 const char *help)
421{
422 int ret = 0;
423
424 if (!component_class || component_class->frozen || !help) {
425 ret = -1;
426 goto end;
427 }
428
429 g_string_assign(component_class->help, help);
430
431end:
432 return ret;
433}
434
38b48196
JG
435const char *bt_component_class_get_name(
436 struct bt_component_class *component_class)
437{
438 return component_class ? component_class->name->str : NULL;
439}
440
d3e4dcd8 441enum bt_component_class_type bt_component_class_get_type(
38b48196
JG
442 struct bt_component_class *component_class)
443{
444 return component_class ? component_class->type :
d3e4dcd8 445 BT_COMPONENT_CLASS_TYPE_UNKNOWN;
38b48196
JG
446}
447
33b34c43 448const char *bt_component_class_get_description(
38b48196
JG
449 struct bt_component_class *component_class)
450{
22e22462
PP
451 return component_class && component_class->description &&
452 component_class->description->str[0] != '\0' ?
6ba0b073 453 component_class->description->str : NULL;
38b48196 454}
7c7c0433 455
5536d9a6
PP
456const char *bt_component_class_get_help(
457 struct bt_component_class *component_class)
458{
22e22462
PP
459 return component_class && component_class->help &&
460 component_class->help->str[0] != '\0' ?
5536d9a6
PP
461 component_class->help->str : NULL;
462}
463
33b34c43
PP
464BT_HIDDEN
465int bt_component_class_add_destroy_listener(struct bt_component_class *class,
466 bt_component_class_destroy_listener_func func, void *data)
7c7c0433 467{
33b34c43 468 int ret = 0;
d3e4dcd8 469 struct bt_component_class_destroy_listener listener;
33b34c43 470
1e4d8103 471 if (!class || class->frozen || !func) {
33b34c43
PP
472 ret = -1;
473 goto end;
474 }
475
476 listener.func = func;
477 listener.data = data;
478 g_array_append_val(class->destroy_listeners, listener);
479
480end:
481 return ret;
7c7c0433 482}
d3e4dcd8
PP
483
484extern int bt_component_class_sink_set_add_iterator_method(
485 struct bt_component_class *component_class,
486 bt_component_class_sink_add_iterator_method add_iterator_method)
487{
488 struct bt_component_class_sink *sink_class;
489 int ret = 0;
490
1e4d8103
PP
491 if (!component_class || component_class->frozen ||
492 !add_iterator_method ||
d3e4dcd8
PP
493 component_class->type != BT_COMPONENT_CLASS_TYPE_SINK) {
494 ret = -1;
495 goto end;
496 }
497
498 sink_class = container_of(component_class,
499 struct bt_component_class_sink, parent);
500 sink_class->methods.add_iterator = add_iterator_method;
501
502end:
503 return ret;
504}
505
506extern int bt_component_class_filter_set_add_iterator_method(
507 struct bt_component_class *component_class,
508 bt_component_class_filter_add_iterator_method add_iterator_method)
509{
510 struct bt_component_class_filter *filter_class;
511 int ret = 0;
512
1e4d8103
PP
513 if (!component_class || component_class->frozen ||
514 !add_iterator_method ||
d3e4dcd8
PP
515 component_class->type !=
516 BT_COMPONENT_CLASS_TYPE_FILTER) {
517 ret = -1;
518 goto end;
519 }
520
521 filter_class = container_of(component_class,
522 struct bt_component_class_filter, parent);
523 filter_class->methods.add_iterator = add_iterator_method;
524
525end:
526 return ret;
527}
1e4d8103
PP
528
529int bt_component_class_freeze(
530 struct bt_component_class *component_class)
531{
532 int ret = 0;
533
534 if (!component_class) {
535 ret = -1;
536 goto end;
537 }
538
539 component_class->frozen = true;
540
541end:
542 return ret;
543}
efa96d5d 544
a67681c1 545struct bt_value *bt_component_class_query(
efa96d5d 546 struct bt_component_class *component_class,
a67681c1 547 const char *object, struct bt_value *params)
efa96d5d
PP
548{
549 struct bt_value *results = NULL;
550
a67681c1
PP
551 if (!component_class || !object || !params ||
552 !component_class->methods.query) {
efa96d5d
PP
553 goto end;
554 }
555
a67681c1
PP
556 results = component_class->methods.query(component_class,
557 object, params);
efa96d5d
PP
558
559end:
560 return results;
561}
This page took 0.050942 seconds and 4 git commands to generate.