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