Commit | Line | Data |
---|---|---|
273b65be JG |
1 | /* |
2 | * event.c | |
3 | * | |
4 | * Babeltrace CTF Writer | |
5 | * | |
6 | * Copyright 2013 EfficiOS Inc. | |
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/ctf-writer/event.h> | |
30 | #include <babeltrace/ctf-writer/event-types.h> | |
31 | #include <babeltrace/ctf-writer/event-fields.h> | |
32 | #include <babeltrace/ctf-writer/event-fields-internal.h> | |
33 | #include <babeltrace/ctf-writer/event-types-internal.h> | |
34 | #include <babeltrace/ctf-writer/event-internal.h> | |
35 | #include <babeltrace/ctf-writer/writer-internal.h> | |
36 | #include <babeltrace/compiler.h> | |
37 | ||
38 | static | |
39 | void bt_ctf_event_class_destroy(struct bt_ctf_ref *ref); | |
40 | static | |
41 | void bt_ctf_event_destroy(struct bt_ctf_ref *ref); | |
42 | ||
43 | struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name) | |
44 | { | |
45 | struct bt_ctf_event_class *event_class = NULL; | |
46 | ||
47 | if (validate_identifier(name)) { | |
48 | goto end; | |
49 | } | |
50 | ||
51 | event_class = g_new0(struct bt_ctf_event_class, 1); | |
52 | if (!event_class) { | |
53 | goto end; | |
54 | } | |
55 | ||
56 | bt_ctf_ref_init(&event_class->ref_count); | |
57 | event_class->name = g_quark_from_string(name); | |
58 | end: | |
59 | return event_class; | |
60 | } | |
61 | ||
62 | int bt_ctf_event_class_add_field(struct bt_ctf_event_class *event_class, | |
63 | struct bt_ctf_field_type *type, | |
64 | const char *name) | |
65 | { | |
66 | int ret = 0; | |
67 | ||
68 | if (!event_class || !type || validate_identifier(name) || | |
69 | event_class->frozen) { | |
70 | ret = -1; | |
71 | goto end; | |
72 | } | |
73 | ||
74 | if (!event_class->fields) { | |
75 | event_class->fields = bt_ctf_field_type_structure_create(); | |
76 | if (!event_class->fields) { | |
77 | ret = -1; | |
78 | goto end; | |
79 | } | |
80 | } | |
81 | ||
82 | ret = bt_ctf_field_type_structure_add_field(event_class->fields, | |
83 | type, name); | |
84 | end: | |
85 | return ret; | |
86 | } | |
87 | ||
88 | void bt_ctf_event_class_get(struct bt_ctf_event_class *event_class) | |
89 | { | |
90 | if (!event_class) { | |
91 | return; | |
92 | } | |
93 | ||
94 | bt_ctf_ref_get(&event_class->ref_count); | |
95 | } | |
96 | ||
97 | void bt_ctf_event_class_put(struct bt_ctf_event_class *event_class) | |
98 | { | |
99 | if (!event_class) { | |
100 | return; | |
101 | } | |
102 | ||
103 | bt_ctf_ref_put(&event_class->ref_count, bt_ctf_event_class_destroy); | |
104 | } | |
105 | ||
106 | struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class) | |
107 | { | |
108 | struct bt_ctf_event *event = NULL; | |
109 | ||
110 | if (!event_class) { | |
111 | goto end; | |
112 | } | |
113 | ||
114 | event = g_new0(struct bt_ctf_event, 1); | |
115 | if (!event) { | |
116 | goto end; | |
117 | } | |
118 | ||
119 | bt_ctf_ref_init(&event->ref_count); | |
120 | bt_ctf_event_class_get(event_class); | |
121 | bt_ctf_event_class_freeze(event_class); | |
122 | event->event_class = event_class; | |
123 | event->context_payload = bt_ctf_field_create(event_class->context); | |
124 | event->fields_payload = bt_ctf_field_create(event_class->fields); | |
125 | end: | |
126 | return event; | |
127 | } | |
128 | ||
129 | int bt_ctf_event_set_payload(struct bt_ctf_event *event, | |
130 | const char *name, | |
131 | struct bt_ctf_field *value) | |
132 | { | |
133 | int ret = 0; | |
134 | ||
135 | if (!event || !value || validate_identifier(name)) { | |
136 | ret = -1; | |
137 | goto end; | |
138 | } | |
139 | ||
140 | ret = bt_ctf_field_structure_set_field(event->fields_payload, | |
141 | name, value); | |
142 | end: | |
143 | return ret; | |
144 | } | |
145 | ||
146 | ||
147 | struct bt_ctf_field *bt_ctf_event_get_payload(struct bt_ctf_event *event, | |
148 | const char *name) | |
149 | { | |
150 | struct bt_ctf_field *field = NULL; | |
151 | ||
152 | if (!event || !name) { | |
153 | goto end; | |
154 | } | |
155 | ||
156 | field = bt_ctf_field_structure_get_field(event->fields_payload, name); | |
157 | end: | |
158 | return field; | |
159 | } | |
160 | ||
161 | void bt_ctf_event_get(struct bt_ctf_event *event) | |
162 | { | |
163 | if (!event) { | |
164 | return; | |
165 | } | |
166 | ||
167 | bt_ctf_ref_get(&event->ref_count); | |
168 | } | |
169 | ||
170 | void bt_ctf_event_put(struct bt_ctf_event *event) | |
171 | { | |
172 | if (!event) { | |
173 | return; | |
174 | } | |
175 | ||
176 | bt_ctf_ref_put(&event->ref_count, bt_ctf_event_destroy); | |
177 | } | |
178 | ||
179 | static | |
180 | void bt_ctf_event_class_destroy(struct bt_ctf_ref *ref) | |
181 | { | |
182 | struct bt_ctf_event_class *event_class; | |
183 | ||
184 | if (!ref) { | |
185 | return; | |
186 | } | |
187 | ||
188 | event_class = container_of(ref, struct bt_ctf_event_class, ref_count); | |
189 | bt_ctf_field_type_put(event_class->context); | |
190 | bt_ctf_field_type_put(event_class->fields); | |
191 | g_free(event_class); | |
192 | } | |
193 | ||
194 | static | |
195 | void bt_ctf_event_destroy(struct bt_ctf_ref *ref) | |
196 | { | |
197 | struct bt_ctf_event *event; | |
198 | ||
199 | if (!ref) { | |
200 | return; | |
201 | } | |
202 | ||
203 | event = container_of(ref, struct bt_ctf_event, | |
204 | ref_count); | |
205 | bt_ctf_event_class_put(event->event_class); | |
206 | bt_ctf_field_put(event->context_payload); | |
207 | bt_ctf_field_put(event->fields_payload); | |
208 | g_free(event); | |
209 | } | |
210 | ||
211 | BT_HIDDEN | |
212 | void bt_ctf_event_class_freeze(struct bt_ctf_event_class *event_class) | |
213 | { | |
214 | assert(event_class); | |
215 | event_class->frozen = 1; | |
216 | bt_ctf_field_type_freeze(event_class->context); | |
217 | bt_ctf_field_type_freeze(event_class->fields); | |
218 | } | |
219 | ||
220 | BT_HIDDEN | |
221 | int bt_ctf_event_class_set_id(struct bt_ctf_event_class *event_class, | |
222 | uint32_t id) | |
223 | { | |
224 | int ret = 0; | |
225 | ||
226 | if (event_class->id_set && id != event_class->id) { | |
227 | ret = -1; | |
228 | goto end; | |
229 | } | |
230 | ||
231 | event_class->id = id; | |
232 | event_class->id_set = 1; | |
233 | end: | |
234 | return ret; | |
235 | } | |
236 | ||
237 | BT_HIDDEN | |
238 | uint32_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class) | |
239 | { | |
240 | assert(event_class); | |
241 | return event_class->id; | |
242 | } | |
243 | ||
244 | BT_HIDDEN | |
245 | int bt_ctf_event_class_set_stream_id(struct bt_ctf_event_class *event_class, | |
246 | uint32_t id) | |
247 | { | |
248 | int ret = 0; | |
249 | ||
250 | assert(event_class); | |
251 | if (event_class->stream_id_set && id != event_class->stream_id) { | |
252 | ret = -1; | |
253 | goto end; | |
254 | } | |
255 | ||
256 | event_class->stream_id = id; | |
257 | event_class->stream_id_set = 1; | |
258 | end: | |
259 | return ret; | |
260 | } | |
261 | ||
262 | BT_HIDDEN | |
263 | int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class, | |
264 | struct metadata_context *context) | |
265 | { | |
266 | int ret = 0; | |
267 | ||
268 | assert(event_class); | |
269 | assert(context); | |
270 | context->current_indentation_level = 1; | |
271 | g_string_assign(context->field_name, ""); | |
272 | g_string_append_printf(context->string, "event {\n\tname = \"%s\";\n\tid = %u;\n\tstream_id = %" PRIu32 ";\n", | |
273 | g_quark_to_string(event_class->name), | |
274 | event_class->id, | |
275 | event_class->stream_id); | |
276 | ||
277 | if (event_class->context) { | |
278 | g_string_append(context->string, "\tcontext := "); | |
279 | ret = bt_ctf_field_type_serialize(event_class->context, | |
280 | context); | |
281 | if (ret) { | |
282 | goto end; | |
283 | } | |
284 | g_string_append(context->string, ";\n"); | |
285 | } | |
286 | ||
287 | if (event_class->fields) { | |
288 | g_string_append(context->string, "\tfields := "); | |
289 | ret = bt_ctf_field_type_serialize(event_class->fields, context); | |
290 | if (ret) { | |
291 | goto end; | |
292 | } | |
293 | g_string_append(context->string, ";\n"); | |
294 | } | |
295 | ||
296 | g_string_append(context->string, "};\n\n"); | |
297 | end: | |
298 | context->current_indentation_level = 0; | |
299 | return ret; | |
300 | } | |
301 | ||
302 | BT_HIDDEN | |
303 | int bt_ctf_event_validate(struct bt_ctf_event *event) | |
304 | { | |
305 | /* Make sure each field's payload has been set */ | |
306 | int ret; | |
307 | ||
308 | assert(event); | |
309 | ret = bt_ctf_field_validate(event->fields_payload); | |
310 | if (ret) { | |
311 | goto end; | |
312 | } | |
313 | ||
314 | if (event->event_class->context) { | |
315 | ret = bt_ctf_field_validate(event->context_payload); | |
316 | } | |
317 | end: | |
318 | return ret; | |
319 | } | |
320 | ||
321 | BT_HIDDEN | |
322 | int bt_ctf_event_serialize(struct bt_ctf_event *event, | |
323 | struct ctf_stream_pos *pos) | |
324 | { | |
325 | int ret = 0; | |
326 | ||
327 | assert(event); | |
328 | assert(pos); | |
329 | if (event->context_payload) { | |
330 | ret = bt_ctf_field_serialize(event->context_payload, pos); | |
331 | if (ret) { | |
332 | goto end; | |
333 | } | |
334 | } | |
335 | ||
336 | if (event->fields_payload) { | |
337 | ret = bt_ctf_field_serialize(event->fields_payload, pos); | |
338 | if (ret) { | |
339 | goto end; | |
340 | } | |
341 | } | |
342 | end: | |
343 | return ret; | |
344 | } | |
345 | ||
346 | BT_HIDDEN | |
347 | int bt_ctf_event_set_timestamp(struct bt_ctf_event *event, | |
348 | uint64_t timestamp) | |
349 | { | |
350 | int ret = 0; | |
351 | ||
352 | assert(event); | |
353 | if (event->timestamp) { | |
354 | ret = -1; | |
355 | goto end; | |
356 | } | |
357 | ||
358 | event->timestamp = timestamp; | |
359 | end: | |
360 | return ret; | |
361 | } | |
362 | ||
363 | BT_HIDDEN | |
364 | uint64_t bt_ctf_event_get_timestamp(struct bt_ctf_event *event) | |
365 | { | |
366 | assert(event); | |
367 | return event->timestamp; | |
368 | } |