Fix: call acting component's "port disconnected" method too
[babeltrace.git] / lib / component / connection.c
1 /*
2 * connection.c
3 *
4 * Babeltrace Connection
5 *
6 * Copyright 2017 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/graph/notification-iterator-internal.h>
30 #include <babeltrace/graph/component-internal.h>
31 #include <babeltrace/graph/component-source-internal.h>
32 #include <babeltrace/graph/component-filter-internal.h>
33 #include <babeltrace/graph/connection-internal.h>
34 #include <babeltrace/graph/private-connection.h>
35 #include <babeltrace/graph/graph-internal.h>
36 #include <babeltrace/graph/port-internal.h>
37 #include <babeltrace/object-internal.h>
38 #include <babeltrace/compiler.h>
39 #include <glib.h>
40
41 static
42 void bt_connection_destroy(struct bt_object *obj)
43 {
44 struct bt_connection *connection = container_of(obj,
45 struct bt_connection, base);
46
47 /*
48 * No bt_put on ports as a connection only holds _weak_ references
49 * to them.
50 */
51 g_free(connection);
52 }
53
54 struct bt_connection *bt_connection_from_private_connection(
55 struct bt_private_connection *private_connection)
56 {
57 return bt_get(bt_connection_from_private(private_connection));
58 }
59
60 BT_HIDDEN
61 struct bt_connection *bt_connection_create(
62 struct bt_graph *graph,
63 struct bt_port *upstream_port,
64 struct bt_port *downstream_port)
65 {
66 struct bt_connection *connection = NULL;
67
68 if (bt_port_get_type(upstream_port) != BT_PORT_TYPE_OUTPUT) {
69 goto end;
70 }
71 if (bt_port_get_type(downstream_port) != BT_PORT_TYPE_INPUT) {
72 goto end;
73 }
74
75 connection = g_new0(struct bt_connection, 1);
76 if (!connection) {
77 goto end;
78 }
79
80 bt_object_init(connection, bt_connection_destroy);
81 /* Weak references are taken, see comment in header. */
82 connection->upstream_port = upstream_port;
83 connection->downstream_port = downstream_port;
84 bt_port_set_connection(upstream_port, connection);
85 bt_port_set_connection(downstream_port, connection);
86 bt_object_set_parent(connection, &graph->base);
87 end:
88 return connection;
89 }
90
91 BT_HIDDEN
92 void bt_connection_disconnect_ports(struct bt_connection *conn)
93 {
94 struct bt_component *downstream_comp = NULL;
95 struct bt_component *upstream_comp = NULL;
96 struct bt_port *downstream_port = conn->downstream_port;
97 struct bt_port *upstream_port = conn->upstream_port;
98
99 if (downstream_port) {
100 downstream_comp = bt_port_get_component(downstream_port);
101 bt_port_set_connection(downstream_port, NULL);
102 conn->downstream_port = NULL;
103 }
104
105 if (upstream_port) {
106 upstream_comp = bt_port_get_component(upstream_port);
107 bt_port_set_connection(upstream_port, NULL);
108 conn->upstream_port = NULL;
109 }
110
111 if (downstream_comp) {
112 bt_component_port_disconnected(downstream_comp,
113 downstream_port);
114 }
115
116 if (upstream_comp) {
117 bt_component_port_disconnected(upstream_comp, upstream_port);
118 }
119
120 if (upstream_comp) {
121 struct bt_graph *graph = bt_component_get_graph(upstream_comp);
122
123 assert(graph);
124 bt_graph_notify_port_disconnected(graph, upstream_comp,
125 upstream_port);
126 bt_put(graph);
127 }
128
129 if (downstream_comp) {
130 struct bt_graph *graph =
131 bt_component_get_graph(downstream_comp);
132
133 assert(graph);
134 bt_graph_notify_port_disconnected(graph, downstream_comp,
135 downstream_port);
136 bt_put(graph);
137 }
138
139 bt_put(downstream_comp);
140 bt_put(upstream_comp);
141 }
142
143 struct bt_port *bt_connection_get_upstream_port(
144 struct bt_connection *connection)
145 {
146 return connection ? bt_get(connection->upstream_port) : NULL;
147 }
148
149 struct bt_port *bt_connection_get_downstream_port(
150 struct bt_connection *connection)
151 {
152 return connection ? bt_get(connection->downstream_port) : NULL;
153 }
154
155 struct bt_notification_iterator *
156 bt_private_connection_create_notification_iterator(
157 struct bt_private_connection *private_connection)
158 {
159 enum bt_notification_iterator_status ret_iterator;
160 enum bt_component_class_type upstream_comp_class_type;
161 struct bt_notification_iterator *iterator = NULL;
162 struct bt_port *upstream_port = NULL;
163 struct bt_component *upstream_component = NULL;
164 struct bt_component_class *upstream_comp_class = NULL;
165 struct bt_connection *connection = NULL;
166 bt_component_class_notification_iterator_init_method init_method = NULL;
167
168 if (!private_connection) {
169 goto error;
170 }
171
172 connection = bt_connection_from_private(private_connection);
173
174 if (!connection->upstream_port || !connection->downstream_port) {
175 goto error;
176 }
177
178 upstream_port = connection->upstream_port;
179 assert(upstream_port);
180 upstream_component = bt_port_get_component(upstream_port);
181 assert(upstream_component);
182 upstream_comp_class = upstream_component->class;
183
184 if (!upstream_component) {
185 goto error;
186 }
187
188 upstream_comp_class_type =
189 bt_component_get_class_type(upstream_component);
190 if (upstream_comp_class_type != BT_COMPONENT_CLASS_TYPE_SOURCE &&
191 upstream_comp_class_type != BT_COMPONENT_CLASS_TYPE_FILTER) {
192 /* Unsupported operation. */
193 goto error;
194 }
195
196 iterator = bt_notification_iterator_create(upstream_component);
197 if (!iterator) {
198 goto error;
199 }
200
201 switch (upstream_comp_class_type) {
202 case BT_COMPONENT_CLASS_TYPE_SOURCE:
203 {
204 struct bt_component_class_source *source_class =
205 container_of(upstream_comp_class,
206 struct bt_component_class_source, parent);
207 init_method = source_class->methods.iterator.init;
208 break;
209 }
210 case BT_COMPONENT_CLASS_TYPE_FILTER:
211 {
212 struct bt_component_class_filter *filter_class =
213 container_of(upstream_comp_class,
214 struct bt_component_class_filter, parent);
215 init_method = filter_class->methods.iterator.init;
216 break;
217 }
218 default:
219 /* Unreachable. */
220 assert(0);
221 }
222
223 if (init_method) {
224 enum bt_notification_iterator_status status = init_method(
225 bt_private_notification_iterator_from_notification_iterator(iterator),
226 bt_private_port_from_port(upstream_port));
227 if (status < 0) {
228 goto error;
229 }
230 }
231
232 ret_iterator = bt_notification_iterator_validate(iterator);
233 if (ret_iterator != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
234 goto error;
235 }
236
237 goto end;
238
239 error:
240 BT_PUT(iterator);
241
242 end:
243 bt_put(upstream_component);
244 return iterator;
245 }
This page took 0.033392 seconds and 4 git commands to generate.