lib: add internal object pool API and use it; adapt plugins/tests
[babeltrace.git] / lib / ctf-ir / stream.c
1 /*
2 * stream.c
3 *
4 * Babeltrace CTF IR - Stream
5 *
6 * Copyright 2013, 2014 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 #define BT_LOG_TAG "STREAM"
30 #include <babeltrace/lib-logging-internal.h>
31
32 #include <babeltrace/assert-pre-internal.h>
33 #include <babeltrace/ctf-ir/stream.h>
34 #include <babeltrace/ctf-ir/stream-internal.h>
35 #include <babeltrace/ctf-ir/stream-class.h>
36 #include <babeltrace/ctf-ir/stream-class-internal.h>
37 #include <babeltrace/ctf-ir/trace.h>
38 #include <babeltrace/ctf-ir/trace-internal.h>
39 #include <babeltrace/ctf-ir/packet-internal.h>
40 #include <babeltrace/ref.h>
41 #include <babeltrace/compiler-internal.h>
42 #include <babeltrace/align-internal.h>
43 #include <babeltrace/assert-internal.h>
44 #include <inttypes.h>
45 #include <unistd.h>
46
47 BT_HIDDEN
48 void bt_stream_common_finalize(struct bt_stream_common *stream)
49 {
50 int i;
51
52 BT_LOGD("Finalizing common stream object: addr=%p, name=\"%s\"",
53 stream, bt_stream_common_get_name(stream));
54
55 /* Call destroy listeners in reverse registration order */
56 if (stream->destroy_listeners) {
57 for (i = stream->destroy_listeners->len - 1; i >= 0; i--) {
58 struct bt_stream_common_destroy_listener *listener =
59 &g_array_index(stream->destroy_listeners,
60 struct bt_stream_common_destroy_listener, i);
61
62 BT_LOGD("Calling destroy listener: func=%p, data=%p, index=%d",
63 listener->func, listener->data, i);
64 listener->func(stream, listener->data);
65 }
66 }
67
68 if (stream->name) {
69 g_string_free(stream->name, TRUE);
70 }
71
72 if (stream->destroy_listeners) {
73 g_array_free(stream->destroy_listeners, TRUE);
74 }
75 }
76
77 static
78 void bt_stream_destroy(struct bt_object *obj)
79 {
80 struct bt_stream *stream = (void *) obj;
81
82 BT_LOGD("Destroying stream object: addr=%p, name=\"%s\"",
83 stream, bt_stream_get_name(stream));
84 bt_object_pool_finalize(&stream->packet_pool);
85 bt_stream_common_finalize((void *) obj);
86 g_free(stream);
87 }
88
89 BT_HIDDEN
90 int bt_stream_common_initialize(
91 struct bt_stream_common *stream,
92 struct bt_stream_class_common *stream_class, const char *name,
93 uint64_t id, bt_object_release_func release_func)
94 {
95 int ret = 0;
96 struct bt_trace_common *trace = NULL;
97
98 bt_object_init(stream, release_func);
99
100 if (!stream_class) {
101 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
102 goto error;
103 }
104
105 BT_LOGD("Initializing common stream object: stream-class-addr=%p, "
106 "stream-class-name=\"%s\", stream-name=\"%s\", "
107 "stream-id=%" PRIu64,
108 stream_class, bt_stream_class_common_get_name(stream_class),
109 name, id);
110 trace = bt_stream_class_common_borrow_trace(stream_class);
111 if (!trace) {
112 BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
113 "stream-class-addr=%p, stream-class-name=\"%s\", "
114 "stream-name=\"%s\"",
115 stream_class,
116 bt_stream_class_common_get_name(stream_class), name);
117 goto error;
118 }
119
120 if (id != -1ULL) {
121 /*
122 * Validate that the given ID is unique amongst all the
123 * existing trace's streams created from the same stream
124 * class.
125 */
126 size_t i;
127
128 for (i = 0; i < trace->streams->len; i++) {
129 struct bt_stream_common *trace_stream =
130 g_ptr_array_index(trace->streams, i);
131
132 if (trace_stream->stream_class != (void *) stream_class) {
133 continue;
134 }
135
136 if (trace_stream->id == id) {
137 BT_LOGW_STR("Invalid parameter: another stream in the same trace already has this ID.");
138 goto error;
139 }
140 }
141 }
142
143 /*
144 * Acquire reference to parent since stream will become publicly
145 * reachable; it needs its parent to remain valid.
146 */
147 bt_object_set_parent(stream, trace);
148 stream->stream_class = stream_class;
149 stream->id = (int64_t) id;
150 stream->destroy_listeners = g_array_new(FALSE, TRUE,
151 sizeof(struct bt_stream_common_destroy_listener));
152 if (!stream->destroy_listeners) {
153 BT_LOGE_STR("Failed to allocate a GArray.");
154 goto error;
155 }
156
157 if (name) {
158 stream->name = g_string_new(name);
159 if (!stream->name) {
160 BT_LOGE_STR("Failed to allocate a GString.");
161 goto error;
162 }
163 }
164
165 BT_LOGD("Set common stream's trace parent: trace-addr=%p", trace);
166
167 /* Add this stream to the trace's streams */
168 BT_LOGD("Created common stream object: addr=%p", stream);
169 goto end;
170
171 error:
172 ret = -1;
173
174 end:
175 return ret;
176 }
177
178 static
179 void bt_stream_free_packet(struct bt_packet *packet, struct bt_stream *stream)
180 {
181 bt_packet_destroy(packet);
182 }
183
184 static
185 struct bt_stream *bt_stream_create_with_id_no_check(
186 struct bt_stream_class *stream_class,
187 const char *name, uint64_t id)
188 {
189 int ret;
190 struct bt_stream *stream = NULL;
191 struct bt_trace *trace = NULL;
192
193 BT_LOGD("Creating stream object: stream-class-addr=%p, "
194 "stream-class-name=\"%s\", stream-name=\"%s\", "
195 "stream-id=%" PRIu64,
196 stream_class, bt_stream_class_get_name(stream_class),
197 name, id);
198
199 trace = BT_FROM_COMMON(bt_stream_class_common_borrow_trace(
200 BT_TO_COMMON(stream_class)));
201 if (!trace) {
202 BT_LOGW("Invalid parameter: cannot create stream from a stream class which is not part of trace: "
203 "stream-class-addr=%p, stream-class-name=\"%s\", "
204 "stream-name=\"%s\"",
205 stream_class, bt_stream_class_get_name(stream_class),
206 name);
207 goto error;
208 }
209
210 if (bt_trace_is_static(trace)) {
211 /*
212 * A static trace has the property that all its stream
213 * classes, clock classes, and streams are definitive:
214 * no more can be added, and each object is also frozen.
215 */
216 BT_LOGW("Invalid parameter: cannot create stream from a stream class which is part of a static trace: "
217 "stream-class-addr=%p, stream-class-name=\"%s\", "
218 "stream-name=\"%s\", trace-addr=%p",
219 stream_class, bt_stream_class_get_name(stream_class),
220 name, trace);
221 goto error;
222 }
223
224 stream = g_new0(struct bt_stream, 1);
225 if (!stream) {
226 BT_LOGE_STR("Failed to allocate one stream.");
227 goto error;
228 }
229
230 ret = bt_stream_common_initialize(BT_TO_COMMON(stream),
231 BT_TO_COMMON(stream_class), name, id, bt_stream_destroy);
232 if (ret) {
233 /* bt_stream_common_initialize() logs errors */
234 goto error;
235 }
236
237 ret = bt_object_pool_initialize(&stream->packet_pool,
238 (bt_object_pool_new_object_func) bt_packet_new,
239 (bt_object_pool_destroy_object_func) bt_stream_free_packet,
240 stream);
241 if (ret) {
242 BT_LOGE("Failed to initialize packet pool: ret=%d", ret);
243 goto error;
244 }
245
246 g_ptr_array_add(trace->common.streams, stream);
247 BT_LOGD("Created stream object: addr=%p", stream);
248 goto end;
249
250 error:
251 BT_PUT(stream);
252
253 end:
254 return stream;
255 }
256
257 struct bt_stream *bt_stream_create(struct bt_stream_class *stream_class,
258 const char *name, uint64_t id_param)
259 {
260 struct bt_stream *stream = NULL;
261 int64_t id = (int64_t) id_param;
262
263 if (!stream_class) {
264 BT_LOGW_STR("Invalid parameter: stream class is NULL.");
265 goto end;
266 }
267
268 if (id < 0) {
269 BT_LOGW("Invalid parameter: invalid stream's ID: "
270 "name=\"%s\", id=%" PRIu64,
271 name, id_param);
272 goto end;
273 }
274
275 stream = bt_stream_create_with_id_no_check(stream_class,
276 name, id_param);
277
278 end:
279 return stream;
280 }
281
282 struct bt_stream_class *bt_stream_borrow_class(struct bt_stream *stream)
283 {
284 return BT_FROM_COMMON(bt_stream_common_borrow_class(BT_TO_COMMON(stream)));
285 }
286
287 const char *bt_stream_get_name(struct bt_stream *stream)
288 {
289 return bt_stream_common_get_name(BT_TO_COMMON(stream));
290 }
291
292 int64_t bt_stream_get_id(struct bt_stream *stream)
293 {
294 return bt_stream_common_get_id(BT_TO_COMMON(stream));
295 }
296
297 BT_HIDDEN
298 void bt_stream_common_add_destroy_listener(struct bt_stream_common *stream,
299 bt_stream_common_destroy_listener_func func, void *data)
300 {
301 struct bt_stream_common_destroy_listener listener;
302
303 BT_ASSERT(stream);
304 BT_ASSERT(func);
305 listener.func = func;
306 listener.data = data;
307 g_array_append_val(stream->destroy_listeners, listener);
308 BT_LOGV("Added stream destroy listener: stream-addr=%p, "
309 "stream-name=\"%s\", func=%p, data=%p",
310 stream, bt_stream_common_get_name(stream), func, data);
311 }
312
313 BT_HIDDEN
314 void bt_stream_common_remove_destroy_listener(struct bt_stream_common *stream,
315 bt_stream_common_destroy_listener_func func, void *data)
316 {
317 size_t i;
318
319 BT_ASSERT(stream);
320 BT_ASSERT(func);
321
322 for (i = 0; i < stream->destroy_listeners->len; i++) {
323 struct bt_stream_common_destroy_listener *listener =
324 &g_array_index(stream->destroy_listeners,
325 struct bt_stream_common_destroy_listener, i);
326
327 if (listener->func == func && listener->data == data) {
328 g_array_remove_index(stream->destroy_listeners, i);
329 i--;
330 BT_LOGV("Removed stream destroy listener: stream-addr=%p, "
331 "stream-name=\"%s\", func=%p, data=%p",
332 stream, bt_stream_common_get_name(stream),
333 func, data);
334 }
335 }
336 }
This page took 0.038861 seconds and 5 git commands to generate.