Remove component prefix from graph, connection and port filenames
[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/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->initializing = true;
99 component->destroy = destroy;
100 end:
101 return ret;
102 }
103
104 enum bt_component_class_type bt_component_get_class_type(
105 struct bt_component *component)
106 {
107 return component ? component->class->type : BT_COMPONENT_CLASS_TYPE_UNKNOWN;
108 }
109
110 BT_HIDDEN
111 struct bt_notification_iterator *bt_component_create_iterator(
112 struct bt_component *component, void *init_method_data)
113 {
114 enum bt_notification_iterator_status ret_iterator;
115 enum bt_component_class_type type;
116 struct bt_notification_iterator *iterator = NULL;
117 struct bt_component_class *class = component->class;
118
119 if (!component) {
120 goto error;
121 }
122
123 type = bt_component_get_class_type(component);
124 if (type != BT_COMPONENT_CLASS_TYPE_SOURCE &&
125 type != BT_COMPONENT_CLASS_TYPE_FILTER) {
126 /* Unsupported operation. */
127 goto error;
128 }
129
130 iterator = bt_notification_iterator_create(component);
131 if (!iterator) {
132 goto error;
133 }
134
135 switch (type) {
136 case BT_COMPONENT_CLASS_TYPE_SOURCE:
137 {
138 struct bt_component_class_source *source_class;
139 enum bt_notification_iterator_status status;
140
141 source_class = container_of(class, struct bt_component_class_source, parent);
142
143 if (source_class->methods.iterator.init) {
144 status = source_class->methods.iterator.init(component,
145 iterator, init_method_data);
146 if (status < 0) {
147 goto error;
148 }
149 }
150 break;
151 }
152 case BT_COMPONENT_CLASS_TYPE_FILTER:
153 {
154 struct bt_component_class_filter *filter_class;
155 enum bt_notification_iterator_status status;
156
157 filter_class = container_of(class, struct bt_component_class_filter, parent);
158
159 if (filter_class->methods.iterator.init) {
160 status = filter_class->methods.iterator.init(component,
161 iterator, init_method_data);
162 if (status < 0) {
163 goto error;
164 }
165 }
166 break;
167 }
168 default:
169 /* Unreachable. */
170 assert(0);
171 }
172
173 ret_iterator = bt_notification_iterator_validate(iterator);
174 if (ret_iterator != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
175 goto error;
176 }
177
178 return iterator;
179 error:
180 BT_PUT(iterator);
181 return iterator;
182 }
183
184 struct bt_component *bt_component_create_with_init_method_data(
185 struct bt_component_class *component_class, const char *name,
186 struct bt_value *params, void *init_method_data)
187 {
188 int ret;
189 struct bt_component *component = NULL;
190 enum bt_component_class_type type;
191
192 if (!component_class) {
193 goto end;
194 }
195
196 type = bt_component_class_get_type(component_class);
197 if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN ||
198 type > BT_COMPONENT_CLASS_TYPE_FILTER) {
199 goto end;
200 }
201
202 component = component_create_funcs[type](component_class, params);
203 if (!component) {
204 goto end;
205 }
206
207 bt_object_init(component, bt_component_destroy);
208 component->name = g_string_new(name);
209 if (!component->name) {
210 BT_PUT(component);
211 goto end;
212 }
213
214 if (component_class->methods.init) {
215 ret = component_class->methods.init(component, params,
216 init_method_data);
217 component->initializing = false;
218 if (ret != BT_COMPONENT_STATUS_OK) {
219 BT_PUT(component);
220 goto end;
221 }
222 }
223
224 component->initializing = false;
225 ret = component_validation_funcs[type](component);
226 if (ret != BT_COMPONENT_STATUS_OK) {
227 BT_PUT(component);
228 goto end;
229 }
230
231 bt_component_class_freeze(component->class);
232 end:
233 return component;
234 }
235
236 struct bt_component *bt_component_create(
237 struct bt_component_class *component_class, const char *name,
238 struct bt_value *params)
239 {
240 return bt_component_create_with_init_method_data(component_class, name,
241 params, NULL);
242 }
243
244 const char *bt_component_get_name(struct bt_component *component)
245 {
246 const char *ret = NULL;
247
248 if (!component) {
249 goto end;
250 }
251
252 ret = component->name->len == 0 ? NULL : component->name->str;
253 end:
254 return ret;
255 }
256
257 enum bt_component_status bt_component_set_name(struct bt_component *component,
258 const char *name)
259 {
260 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
261
262 if (!component || !name || name[0] == '\0') {
263 ret = BT_COMPONENT_STATUS_INVALID;
264 goto end;
265 }
266
267 g_string_assign(component->name, name);
268 end:
269 return ret;
270 }
271
272 struct bt_component_class *bt_component_get_class(
273 struct bt_component *component)
274 {
275 return component ? bt_get(component->class) : NULL;
276 }
277
278 void *bt_component_get_private_data(struct bt_component *component)
279 {
280 return component ? component->user_data : NULL;
281 }
282
283 enum bt_component_status
284 bt_component_set_private_data(struct bt_component *component,
285 void *data)
286 {
287 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
288
289 if (!component || !component->initializing) {
290 ret = BT_COMPONENT_STATUS_INVALID;
291 goto end;
292 }
293
294 component->user_data = data;
295 end:
296 return ret;
297 }
298
299 BT_HIDDEN
300 void bt_component_set_graph(struct bt_component *component,
301 struct bt_graph *graph)
302 {
303 struct bt_object *parent = bt_object_get_parent(&component->base);
304
305 assert(!parent || parent == &graph->base);
306 if (!parent) {
307 bt_object_set_parent(component, &graph->base);
308 }
309 bt_put(parent);
310 }
311
312 struct bt_graph *bt_component_get_graph(
313 struct bt_component *component)
314 {
315 return (struct bt_graph *) bt_object_get_parent(&component->base);
316 }
317
318 BT_HIDDEN
319 int bt_component_init_input_ports(struct bt_component *component,
320 GPtrArray **input_ports)
321 {
322 int ret = 0;
323 struct bt_port *default_port;
324
325 *input_ports = g_ptr_array_new_with_free_func(bt_object_release);
326 if (!*input_ports) {
327 ret = -1;
328 goto end;
329 }
330
331 default_port = bt_component_add_port(component, *input_ports,
332 BT_PORT_TYPE_INPUT, DEFAULT_INPUT_PORT_NAME);
333 if (!default_port) {
334 ret = -1;
335 goto end;
336 }
337 bt_put(default_port);
338 end:
339 return ret;
340 }
341
342 BT_HIDDEN
343 int bt_component_init_output_ports(struct bt_component *component,
344 GPtrArray **output_ports)
345 {
346 int ret = 0;
347 struct bt_port *default_port;
348
349 *output_ports = g_ptr_array_new_with_free_func(bt_object_release);
350 if (!*output_ports) {
351 ret = -1;
352 goto end;
353 }
354
355 default_port = bt_component_add_port(component, *output_ports,
356 BT_PORT_TYPE_OUTPUT, DEFAULT_OUTPUT_PORT_NAME);
357 if (!default_port) {
358 ret = -1;
359 goto end;
360 }
361 bt_put(default_port);
362 end:
363 return ret;
364 }
365
366 BT_HIDDEN
367 struct bt_port *bt_component_get_port(GPtrArray *ports, const char *name)
368 {
369 size_t i;
370 struct bt_port *ret_port = NULL;
371
372 for (i = 0; i < ports->len; i++) {
373 struct bt_port *port = g_ptr_array_index(ports, i);
374 const char *port_name = bt_port_get_name(port);
375
376 if (!port_name) {
377 continue;
378 }
379
380 if (!strcmp(name, port_name)) {
381 ret_port = bt_get(port);
382 break;
383 }
384 }
385
386 return ret_port;
387 }
388
389 BT_HIDDEN
390 struct bt_port *bt_component_get_port_at_index(GPtrArray *ports, int index)
391 {
392 struct bt_port *port = NULL;
393
394 if (index < 0 || index >= ports->len) {
395 goto end;
396 }
397
398 port = bt_get(g_ptr_array_index(ports, index));
399 end:
400 return port;
401 }
402
403 BT_HIDDEN
404 struct bt_port *bt_component_add_port(
405 struct bt_component *component,GPtrArray *ports,
406 enum bt_port_type port_type, const char *name)
407 {
408 size_t i;
409 struct bt_port *new_port = NULL;
410
411 if (!component->initializing || !name || *name == '\0') {
412 goto end;
413 }
414
415 /* Look for a port having the same name. */
416 for (i = 0; i < ports->len; i++) {
417 const char *port_name;
418 struct bt_port *port = g_ptr_array_index(
419 ports, i);
420
421 port_name = bt_port_get_name(port);
422 if (!port_name) {
423 continue;
424 }
425
426 if (!strcmp(name, port_name)) {
427 /* Port name clash, abort. */
428 goto end;
429 }
430 }
431
432 new_port = bt_port_create(component, port_type, name);
433 if (!new_port) {
434 goto end;
435 }
436
437 /*
438 * No name clash, add the port.
439 * The component is now the port's parent; it should _not_
440 * hold a reference to the port since the port's lifetime
441 * is now protected by the component's own lifetime.
442 */
443 g_ptr_array_add(ports, new_port);
444 end:
445 return new_port;
446 }
447
448 BT_HIDDEN
449 enum bt_component_status bt_component_remove_port(
450 struct bt_component *component, GPtrArray *ports,
451 const char *name)
452 {
453 size_t i;
454 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
455
456 if (!component->initializing || !name) {
457 status = BT_COMPONENT_STATUS_INVALID;
458 goto end;
459 }
460
461 for (i = 0; i < ports->len; i++) {
462 const char *port_name;
463 struct bt_port *port = g_ptr_array_index(ports, i);
464
465 port_name = bt_port_get_name(port);
466 if (!port_name) {
467 continue;
468 }
469
470 if (!strcmp(name, port_name)) {
471 g_ptr_array_remove_index(ports, i);
472 goto end;
473 }
474 }
475 status = BT_COMPONENT_STATUS_NOT_FOUND;
476 end:
477 return status;
478 }
479
480 BT_HIDDEN
481 enum bt_component_status bt_component_new_connection(
482 struct bt_component *component, struct bt_port *own_port,
483 struct bt_connection *connection)
484 {
485 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
486
487 if (component->class->methods.new_connection_method) {
488 status = component->class->methods.new_connection_method(
489 own_port, connection);
490 }
491
492 return status;
493 }
This page took 0.043533 seconds and 4 git commands to generate.