0f5337257c4810fada3ca18272db7182bb129b0e
[babeltrace.git] / lib / component / component-class.c
1 /*
2 * component-class.c
3 *
4 * Babeltrace Plugin Component Class
5 *
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
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>
30 #include <babeltrace/component/component-class-internal.h>
31 #include <babeltrace/ref.h>
32 #include <stdbool.h>
33 #include <glib.h>
34
35 static
36 void bt_component_class_destroy(struct bt_object *obj)
37 {
38 struct bt_component_class *class;
39 int i;
40
41 assert(obj);
42 class = container_of(obj, struct bt_component_class, base);
43
44 /* Call destroy listeners in reverse registration order */
45 for (i = class->destroy_listeners->len - 1; i >= 0; i--) {
46 struct bt_component_class_destroy_listener *listener =
47 &g_array_index(class->destroy_listeners,
48 struct bt_component_class_destroy_listener,
49 i);
50
51 listener->func(class, listener->data);
52 }
53
54 if (class->name) {
55 g_string_free(class->name, TRUE);
56 }
57 if (class->description) {
58 g_string_free(class->description, TRUE);
59 }
60 if (class->help) {
61 g_string_free(class->help, TRUE);
62 }
63 if (class->destroy_listeners) {
64 g_array_free(class->destroy_listeners, TRUE);
65 }
66
67 g_free(class);
68 }
69
70 static
71 int bt_component_class_init(struct bt_component_class *class,
72 enum bt_component_class_type type, const char *name)
73 {
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
88 class->help = g_string_new(NULL);
89 if (!class->help) {
90 goto error;
91 }
92
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;
100
101 error:
102 BT_PUT(class);
103 ret = -1;
104
105 end:
106 return ret;
107 }
108
109 struct bt_component_class *bt_component_class_source_create(const char *name,
110 bt_component_class_notification_iterator_get_method notification_iterator_get_method,
111 bt_component_class_notification_iterator_next_method notification_iterator_next_method)
112 {
113 struct bt_component_class_source *source_class = NULL;
114 int ret;
115
116 if (!name || !notification_iterator_get_method ||
117 !notification_iterator_next_method) {
118 goto end;
119 }
120
121 source_class = g_new0(struct bt_component_class_source, 1);
122 if (!source_class) {
123 goto end;
124 }
125
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
138 source_class->methods.iterator.get = notification_iterator_get_method;
139 source_class->methods.iterator.next = notification_iterator_next_method;
140
141 end:
142 return &source_class->parent;
143 }
144
145 struct bt_component_class *bt_component_class_filter_create(const char *name,
146 bt_component_class_notification_iterator_get_method notification_iterator_get_method,
147 bt_component_class_notification_iterator_next_method notification_iterator_next_method)
148 {
149 struct bt_component_class_filter *filter_class = NULL;
150 int ret;
151
152 if (!name || !notification_iterator_get_method ||
153 !notification_iterator_next_method) {
154 goto end;
155 }
156
157 filter_class = g_new0(struct bt_component_class_filter, 1);
158 if (!filter_class) {
159 goto end;
160 }
161
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;
171 goto end;
172 }
173
174 filter_class->methods.iterator.get = notification_iterator_get_method;
175 filter_class->methods.iterator.next = notification_iterator_next_method;
176
177 end:
178 return &filter_class->parent;
179 }
180
181 struct 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
210 end:
211 return &sink_class->parent;
212 }
213
214 int 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
220 if (!component_class || component_class->frozen || !init_method) {
221 ret = -1;
222 goto end;
223 }
224
225 component_class->methods.init = init_method;
226
227 end:
228 return ret;
229 }
230
231 int bt_component_class_set_query_method(
232 struct bt_component_class *component_class,
233 bt_component_class_query_method query_method)
234 {
235 int ret = 0;
236
237 if (!component_class || component_class->frozen || !query_method) {
238 ret = -1;
239 goto end;
240 }
241
242 component_class->methods.query = query_method;
243
244 end:
245 return ret;
246 }
247
248 int bt_component_class_set_accept_port_connection_method(
249 struct bt_component_class *component_class,
250 bt_component_class_accept_port_connection_method method)
251 {
252 int ret = 0;
253
254 if (!component_class || component_class->frozen || !method) {
255 ret = -1;
256 goto end;
257 }
258
259 component_class->methods.accept_port_connection = method;
260
261 end:
262 return ret;
263 }
264
265 int bt_component_class_set_port_disconnected_method(
266 struct bt_component_class *component_class,
267 bt_component_class_port_disconnected_method method)
268 {
269 int ret = 0;
270
271 if (!component_class || component_class->frozen || !method) {
272 ret = -1;
273 goto end;
274 }
275
276 component_class->methods.port_disconnected = method;
277
278 end:
279 return ret;
280 }
281
282 int bt_component_class_set_finalize_method(
283 struct bt_component_class *component_class,
284 bt_component_class_finalize_method finalize_method)
285 {
286 int ret = 0;
287
288 if (!component_class || component_class->frozen || !finalize_method) {
289 ret = -1;
290 goto end;
291 }
292
293 component_class->methods.finalize = finalize_method;
294
295 end:
296 return ret;
297 }
298
299 int bt_component_class_source_set_notification_iterator_init_method(
300 struct bt_component_class *component_class,
301 bt_component_class_notification_iterator_init_method notification_iterator_init_method)
302 {
303 struct bt_component_class_source *source_class;
304 int ret = 0;
305
306 if (!component_class || component_class->frozen ||
307 !notification_iterator_init_method ||
308 component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
309 ret = -1;
310 goto end;
311 }
312
313 source_class = container_of(component_class,
314 struct bt_component_class_source, parent);
315 source_class->methods.iterator.init = notification_iterator_init_method;
316
317 end:
318 return ret;
319 }
320
321 int bt_component_class_source_set_notification_iterator_finalize_method(
322 struct bt_component_class *component_class,
323 bt_component_class_notification_iterator_finalize_method notification_iterator_finalize_method)
324 {
325 struct bt_component_class_source *source_class;
326 int ret = 0;
327
328 if (!component_class || component_class->frozen ||
329 !notification_iterator_finalize_method ||
330 component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
331 ret = -1;
332 goto end;
333 }
334
335 source_class = container_of(component_class,
336 struct bt_component_class_source, parent);
337 source_class->methods.iterator.finalize =
338 notification_iterator_finalize_method;
339
340 end:
341 return ret;
342 }
343
344 int bt_component_class_source_set_notification_iterator_seek_time_method(
345 struct bt_component_class *component_class,
346 bt_component_class_notification_iterator_seek_time_method notification_iterator_seek_time_method)
347 {
348 struct bt_component_class_source *source_class;
349 int ret = 0;
350
351 if (!component_class || component_class->frozen ||
352 !notification_iterator_seek_time_method ||
353 component_class->type != BT_COMPONENT_CLASS_TYPE_SOURCE) {
354 ret = -1;
355 goto end;
356 }
357
358 source_class = container_of(component_class,
359 struct bt_component_class_source, parent);
360 source_class->methods.iterator.seek_time =
361 notification_iterator_seek_time_method;
362
363 end:
364 return ret;
365 }
366
367 int bt_component_class_filter_set_notification_iterator_init_method(
368 struct bt_component_class *component_class,
369 bt_component_class_notification_iterator_init_method notification_iterator_init_method)
370 {
371 struct bt_component_class_filter *filter_class;
372 int ret = 0;
373
374 if (!component_class || component_class->frozen ||
375 !notification_iterator_init_method ||
376 component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
377 ret = -1;
378 goto end;
379 }
380
381 filter_class = container_of(component_class,
382 struct bt_component_class_filter, parent);
383 filter_class->methods.iterator.init = notification_iterator_init_method;
384
385 end:
386 return ret;
387 }
388
389 int bt_component_class_filter_set_notification_iterator_finalize_method(
390 struct bt_component_class *component_class,
391 bt_component_class_notification_iterator_finalize_method notification_iterator_finalize_method)
392 {
393 struct bt_component_class_filter *filter_class;
394 int ret = 0;
395
396 if (!component_class || component_class->frozen ||
397 !notification_iterator_finalize_method ||
398 component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
399 ret = -1;
400 goto end;
401 }
402
403 filter_class = container_of(component_class,
404 struct bt_component_class_filter, parent);
405 filter_class->methods.iterator.finalize =
406 notification_iterator_finalize_method;
407
408 end:
409 return ret;
410 }
411
412 int bt_component_class_filter_set_notification_iterator_seek_time_method(
413 struct bt_component_class *component_class,
414 bt_component_class_notification_iterator_seek_time_method notification_iterator_seek_time_method)
415 {
416 struct bt_component_class_filter *filter_class;
417 int ret = 0;
418
419 if (!component_class || component_class->frozen ||
420 !notification_iterator_seek_time_method ||
421 component_class->type != BT_COMPONENT_CLASS_TYPE_FILTER) {
422 ret = -1;
423 goto end;
424 }
425
426 filter_class = container_of(component_class,
427 struct bt_component_class_filter, parent);
428 filter_class->methods.iterator.seek_time =
429 notification_iterator_seek_time_method;
430
431 end:
432 return ret;
433 }
434
435 int bt_component_class_set_description(
436 struct bt_component_class *component_class,
437 const char *description)
438 {
439 int ret = 0;
440
441 if (!component_class || component_class->frozen || !description) {
442 ret = -1;
443 goto end;
444 }
445
446 g_string_assign(component_class->description, description);
447
448 end:
449 return ret;
450 }
451
452 int bt_component_class_set_help(
453 struct bt_component_class *component_class,
454 const char *help)
455 {
456 int ret = 0;
457
458 if (!component_class || component_class->frozen || !help) {
459 ret = -1;
460 goto end;
461 }
462
463 g_string_assign(component_class->help, help);
464
465 end:
466 return ret;
467 }
468
469 const char *bt_component_class_get_name(
470 struct bt_component_class *component_class)
471 {
472 return component_class ? component_class->name->str : NULL;
473 }
474
475 enum bt_component_class_type bt_component_class_get_type(
476 struct bt_component_class *component_class)
477 {
478 return component_class ? component_class->type :
479 BT_COMPONENT_CLASS_TYPE_UNKNOWN;
480 }
481
482 const char *bt_component_class_get_description(
483 struct bt_component_class *component_class)
484 {
485 return component_class && component_class->description &&
486 component_class->description->str[0] != '\0' ?
487 component_class->description->str : NULL;
488 }
489
490 const char *bt_component_class_get_help(
491 struct bt_component_class *component_class)
492 {
493 return component_class && component_class->help &&
494 component_class->help->str[0] != '\0' ?
495 component_class->help->str : NULL;
496 }
497
498 BT_HIDDEN
499 int bt_component_class_add_destroy_listener(struct bt_component_class *class,
500 bt_component_class_destroy_listener_func func, void *data)
501 {
502 int ret = 0;
503 struct bt_component_class_destroy_listener listener;
504
505 if (!class || class->frozen || !func) {
506 ret = -1;
507 goto end;
508 }
509
510 listener.func = func;
511 listener.data = data;
512 g_array_append_val(class->destroy_listeners, listener);
513
514 end:
515 return ret;
516 }
517
518 int bt_component_class_freeze(
519 struct bt_component_class *component_class)
520 {
521 int ret = 0;
522
523 if (!component_class) {
524 ret = -1;
525 goto end;
526 }
527
528 component_class->frozen = true;
529
530 end:
531 return ret;
532 }
533
534 struct bt_value *bt_component_class_query(
535 struct bt_component_class *component_class,
536 const char *object, struct bt_value *params)
537 {
538 struct bt_value *results = NULL;
539
540 if (!component_class || !object || !params ||
541 !component_class->methods.query) {
542 goto end;
543 }
544
545 results = component_class->methods.query(component_class,
546 object, params);
547
548 end:
549 return results;
550 }
This page took 0.051589 seconds and 3 git commands to generate.