Add ports to the source, filter and sink component interfaces
[babeltrace.git] / lib / component / component.c
1 /*
2 * component.c
3 *
4 * Babeltrace Plugin Component
5 *
6 * Copyright 2015 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/component/component.h>
30 #include <babeltrace/component/component-internal.h>
31 #include <babeltrace/component/component-class-internal.h>
32 #include <babeltrace/component/component-source-internal.h>
33 #include <babeltrace/component/component-filter-internal.h>
34 #include <babeltrace/component/component-sink-internal.h>
35 #include <babeltrace/component/component-graph-internal.h>
36 #include <babeltrace/component/notification/iterator-internal.h>
37 #include <babeltrace/babeltrace-internal.h>
38 #include <babeltrace/compiler.h>
39 #include <babeltrace/ref.h>
40
41 static
42 struct bt_component * (* const component_create_funcs[])(
43 struct bt_component_class *, struct bt_value *) = {
44 [BT_COMPONENT_CLASS_TYPE_SOURCE] = bt_component_source_create,
45 [BT_COMPONENT_CLASS_TYPE_SINK] = bt_component_sink_create,
46 [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_create,
47 };
48
49 static
50 enum bt_component_status (* const component_validation_funcs[])(
51 struct bt_component *) = {
52 [BT_COMPONENT_CLASS_TYPE_SOURCE] = bt_component_source_validate,
53 [BT_COMPONENT_CLASS_TYPE_SINK] = bt_component_sink_validate,
54 [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_validate,
55 };
56
57 static
58 void bt_component_destroy(struct bt_object *obj)
59 {
60 struct bt_component *component = NULL;
61 struct bt_component_class *component_class = NULL;
62
63 if (!obj) {
64 return;
65 }
66
67 component = container_of(obj, struct bt_component, base);
68 component_class = component->class;
69
70 /*
71 * User data is destroyed first, followed by the concrete component
72 * instance.
73 */
74 if (component->class->methods.destroy) {
75 component->class->methods.destroy(component);
76 }
77
78 if (component->destroy) {
79 component->destroy(component);
80 }
81
82 g_string_free(component->name, TRUE);
83 bt_put(component_class);
84 g_free(component);
85 }
86
87 BT_HIDDEN
88 enum bt_component_status bt_component_init(struct bt_component *component,
89 bt_component_class_destroy_method destroy)
90 {
91 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
92
93 if (!component) {
94 ret = BT_COMPONENT_STATUS_INVALID;
95 goto end;
96 }
97
98 component->destroy = destroy;
99 end:
100 return ret;
101 }
102
103 enum bt_component_class_type bt_component_get_class_type(
104 struct bt_component *component)
105 {
106 return component ? component->class->type : BT_COMPONENT_CLASS_TYPE_UNKNOWN;
107 }
108
109 BT_HIDDEN
110 struct bt_notification_iterator *bt_component_create_iterator(
111 struct bt_component *component, void *init_method_data)
112 {
113 enum bt_notification_iterator_status ret_iterator;
114 enum bt_component_class_type type;
115 struct bt_notification_iterator *iterator = NULL;
116 struct bt_component_class *class = component->class;
117
118 if (!component) {
119 goto error;
120 }
121
122 type = bt_component_get_class_type(component);
123 if (type != BT_COMPONENT_CLASS_TYPE_SOURCE &&
124 type != BT_COMPONENT_CLASS_TYPE_FILTER) {
125 /* Unsupported operation. */
126 goto error;
127 }
128
129 iterator = bt_notification_iterator_create(component);
130 if (!iterator) {
131 goto error;
132 }
133
134 switch (type) {
135 case BT_COMPONENT_CLASS_TYPE_SOURCE:
136 {
137 struct bt_component_class_source *source_class;
138 enum bt_notification_iterator_status status;
139
140 source_class = container_of(class, struct bt_component_class_source, parent);
141
142 if (source_class->methods.iterator.init) {
143 status = source_class->methods.iterator.init(component,
144 iterator, init_method_data);
145 if (status < 0) {
146 goto error;
147 }
148 }
149 break;
150 }
151 case BT_COMPONENT_CLASS_TYPE_FILTER:
152 {
153 struct bt_component_class_filter *filter_class;
154 enum bt_notification_iterator_status status;
155
156 filter_class = container_of(class, struct bt_component_class_filter, parent);
157
158 if (filter_class->methods.iterator.init) {
159 status = filter_class->methods.iterator.init(component,
160 iterator, init_method_data);
161 if (status < 0) {
162 goto error;
163 }
164 }
165 break;
166 }
167 default:
168 /* Unreachable. */
169 assert(0);
170 }
171
172 ret_iterator = bt_notification_iterator_validate(iterator);
173 if (ret_iterator != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
174 goto error;
175 }
176
177 return iterator;
178 error:
179 BT_PUT(iterator);
180 return iterator;
181 }
182
183 struct bt_component *bt_component_create_with_init_method_data(
184 struct bt_component_class *component_class, const char *name,
185 struct bt_value *params, void *init_method_data)
186 {
187 int ret;
188 struct bt_component *component = NULL;
189 enum bt_component_class_type type;
190
191 if (!component_class) {
192 goto end;
193 }
194
195 type = bt_component_class_get_type(component_class);
196 if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN ||
197 type > BT_COMPONENT_CLASS_TYPE_FILTER) {
198 goto end;
199 }
200
201 component = component_create_funcs[type](component_class, params);
202 if (!component) {
203 goto end;
204 }
205
206 bt_object_init(component, bt_component_destroy);
207 component->name = g_string_new(name);
208 if (!component->name) {
209 BT_PUT(component);
210 goto end;
211 }
212
213 component->initializing = true;
214
215 if (component_class->methods.init) {
216 ret = component_class->methods.init(component, params,
217 init_method_data);
218 component->initializing = false;
219 if (ret != BT_COMPONENT_STATUS_OK) {
220 BT_PUT(component);
221 goto end;
222 }
223 }
224
225 component->initializing = false;
226 ret = component_validation_funcs[type](component);
227 if (ret != BT_COMPONENT_STATUS_OK) {
228 BT_PUT(component);
229 goto end;
230 }
231
232 bt_component_class_freeze(component->class);
233 end:
234 return component;
235 }
236
237 struct bt_component *bt_component_create(
238 struct bt_component_class *component_class, const char *name,
239 struct bt_value *params)
240 {
241 return bt_component_create_with_init_method_data(component_class, name,
242 params, NULL);
243 }
244
245 const char *bt_component_get_name(struct bt_component *component)
246 {
247 const char *ret = NULL;
248
249 if (!component) {
250 goto end;
251 }
252
253 ret = component->name->len == 0 ? NULL : component->name->str;
254 end:
255 return ret;
256 }
257
258 enum bt_component_status bt_component_set_name(struct bt_component *component,
259 const char *name)
260 {
261 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
262
263 if (!component || !name || name[0] == '\0') {
264 ret = BT_COMPONENT_STATUS_INVALID;
265 goto end;
266 }
267
268 g_string_assign(component->name, name);
269 end:
270 return ret;
271 }
272
273 struct bt_component_class *bt_component_get_class(
274 struct bt_component *component)
275 {
276 return component ? bt_get(component->class) : NULL;
277 }
278
279 void *bt_component_get_private_data(struct bt_component *component)
280 {
281 return component ? component->user_data : NULL;
282 }
283
284 enum bt_component_status
285 bt_component_set_private_data(struct bt_component *component,
286 void *data)
287 {
288 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
289
290 if (!component || !component->initializing) {
291 ret = BT_COMPONENT_STATUS_INVALID;
292 goto end;
293 }
294
295 component->user_data = data;
296 end:
297 return ret;
298 }
299
300 BT_HIDDEN
301 enum bt_component_status bt_component_set_graph(struct bt_component *component,
302 struct bt_graph *graph)
303 {
304 bt_object_set_parent(component, &graph->base);
305 return BT_COMPONENT_STATUS_OK;
306 }
307
308 struct bt_graph *bt_component_get_graph(
309 struct bt_component *component)
310 {
311 return (struct bt_graph *) bt_object_get_parent(&component->base);
312 }
313
314 BT_HIDDEN
315 int bt_component_init_input_ports(struct bt_component *component,
316 GPtrArray **input_ports)
317 {
318 int ret = 0;
319 struct bt_port *default_port;
320
321 *input_ports = g_ptr_array_new_with_free_func(bt_object_release);
322 if (*input_ports) {
323 ret = -1;
324 goto end;
325 }
326
327 default_port = bt_port_create(component, BT_PORT_TYPE_INPUT,
328 DEFAULT_INPUT_PORT_NAME);
329 if (!default_port) {
330 ret = -1;
331 goto end;
332 }
333
334 g_ptr_array_add(*input_ports, default_port);
335 end:
336 return ret;
337 }
338
339 BT_HIDDEN
340 int bt_component_init_output_ports(struct bt_component *component,
341 GPtrArray **output_ports)
342 {
343 int ret = 0;
344 struct bt_port *default_port;
345
346 *output_ports = g_ptr_array_new_with_free_func(bt_object_release);
347 if (*output_ports) {
348 ret = -1;
349 goto end;
350 }
351
352 default_port = bt_port_create(component, BT_PORT_TYPE_OUTPUT,
353 DEFAULT_OUTPUT_PORT_NAME);
354 if (!default_port) {
355 ret = -1;
356 goto end;
357 }
358
359 g_ptr_array_add(*output_ports, default_port);
360 end:
361 return ret;
362 }
363
364 BT_HIDDEN
365 struct bt_port *bt_component_get_port(GPtrArray *ports, const char *name)
366 {
367 size_t i;
368 struct bt_port *ret_port = NULL;
369
370 for (i = 0; i < ports->len; i++) {
371 struct bt_port *port = g_ptr_array_index(ports, i);
372 const char *port_name = bt_port_get_name(port);
373
374 if (!port_name) {
375 continue;
376 }
377
378 if (!strcmp(name, port_name)) {
379 ret_port = bt_get(port);
380 break;
381 }
382 }
383
384 return ret_port;
385 }
386
387 BT_HIDDEN
388 struct bt_port *bt_component_get_port_at_index(GPtrArray *ports, int index)
389 {
390 struct bt_port *port = NULL;
391
392 if (index < 0 || index >= ports->len) {
393 goto end;
394 }
395
396 port = bt_get(g_ptr_array_index(ports, index));
397 end:
398 return port;
399 }
400
401 BT_HIDDEN
402 struct bt_port *bt_component_add_port(
403 struct bt_component *component,GPtrArray *ports,
404 enum bt_port_type port_type, const char *name)
405 {
406 size_t i;
407 struct bt_port *new_port;
408
409 if (!component->initializing || !name || *name == '\0') {
410 new_port = NULL;
411 goto end;
412 }
413
414 new_port = bt_port_create(component, port_type, name);
415 if (!new_port) {
416 goto end;
417 }
418
419 /* Look for a port having the same name. */
420 for (i = 0; i < ports->len; i++) {
421 const char *port_name;
422 struct bt_port *port = g_ptr_array_index(
423 ports, i);
424
425 port_name = bt_port_get_name(port);
426 if (!port_name) {
427 continue;
428 }
429
430 if (!strcmp(name, port_name)) {
431 /* Port name clash, abort. */
432 goto error;
433 }
434 }
435
436 /* No name clash, add the port. */
437 g_ptr_array_add(ports, bt_get(new_port));
438 end:
439 return new_port;
440 error:
441 BT_PUT(new_port);
442 goto end;
443 }
444
445 BT_HIDDEN
446 enum bt_component_status bt_component_remove_port(
447 struct bt_component *component, GPtrArray *ports,
448 const char *name)
449 {
450 size_t i;
451 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
452
453 if (!component->initializing || !name) {
454 status = BT_COMPONENT_STATUS_INVALID;
455 goto end;
456 }
457
458 for (i = 0; i < ports->len; i++) {
459 const char *port_name;
460 struct bt_port *port = g_ptr_array_index(ports, i);
461
462 port_name = bt_port_get_name(port);
463 if (!port_name) {
464 continue;
465 }
466
467 if (!strcmp(name, port_name)) {
468 g_ptr_array_remove_index(ports, i);
469 goto end;
470 }
471 }
472 status = BT_COMPONENT_STATUS_NOT_FOUND;
473 end:
474 return status;
475 }
This page took 0.038077 seconds and 4 git commands to generate.