ea41344a72ef1ff5c5957383fe96e9a49de28daf
[babeltrace.git] / formats / ctf / callbacks.c
1 /*
2 * callbacks.c
3 *
4 * Babeltrace Library
5 *
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
7 *
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@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
21 #include <babeltrace/babeltrace.h>
22 #include <babeltrace/babeltrace-internal.h>
23 #include <babeltrace/context.h>
24 #include <babeltrace/context-internal.h>
25 #include <babeltrace/ctf-ir/metadata.h>
26 #include <babeltrace/iterator-internal.h>
27 #include <babeltrace/ctf/events.h>
28 #include <babeltrace/ctf/events-internal.h>
29 #include <babeltrace/ctf/callbacks-internal.h>
30 #include <inttypes.h>
31
32 static
33 struct bt_dependencies *_babeltrace_dependencies_create(const char *first,
34 va_list ap)
35 {
36 const char *iter;
37 struct bt_dependencies *dep;
38
39 dep = g_new0(struct bt_dependencies, 1);
40 dep->refcount = 1;
41 dep->deps = g_array_new(FALSE, TRUE, sizeof(GQuark));
42 iter = first;
43 while (iter) {
44 GQuark q = g_quark_from_string(iter);
45 g_array_append_val(dep->deps, q);
46 iter = va_arg(ap, const char *);
47 }
48 return dep;
49 }
50
51 struct bt_dependencies *babeltrace_dependencies_create(const char *first, ...)
52 {
53 va_list ap;
54 struct bt_dependencies *deps;
55
56 va_start(ap, first);
57 deps = _babeltrace_dependencies_create(first, ap);
58 va_end(ap);
59 return deps;
60 }
61
62 /*
63 * bt_ctf_iter_add_callback: Add a callback to CTF iterator.
64 */
65 int bt_ctf_iter_add_callback(struct bt_ctf_iter *iter,
66 bt_intern_str event, void *private_data, int flags,
67 enum bt_cb_ret (*callback)(struct bt_ctf_event *ctf_data,
68 void *private_data),
69 struct bt_dependencies *depends,
70 struct bt_dependencies *weak_depends,
71 struct bt_dependencies *provides)
72 {
73 int i, stream_id;
74 gpointer *event_id_ptr;
75 unsigned long event_id;
76 struct trace_collection *tc = iter->parent.ctx->tc;
77
78 for (i = 0; i < tc->array->len; i++) {
79 struct ctf_trace *tin;
80 struct trace_descriptor *td_read;
81
82 td_read = g_ptr_array_index(tc->array, i);
83 tin = container_of(td_read, struct ctf_trace, parent);
84
85 for (stream_id = 0; stream_id < tin->streams->len; stream_id++) {
86 struct ctf_stream_declaration *stream;
87 struct bt_stream_callbacks *bt_stream_cb = NULL;
88 struct bt_callback_chain *bt_chain = NULL;
89 struct bt_callback new_callback;
90
91 stream = g_ptr_array_index(tin->streams, stream_id);
92
93 if (stream_id >= iter->callbacks->len) {
94 g_array_set_size(iter->callbacks, stream->stream_id + 1);
95 }
96 bt_stream_cb = &g_array_index(iter->callbacks,
97 struct bt_stream_callbacks, stream->stream_id);
98 if (!bt_stream_cb->per_id_callbacks) {
99 bt_stream_cb->per_id_callbacks = g_array_new(FALSE, TRUE,
100 sizeof(struct bt_callback_chain));
101 }
102
103 if (event) {
104 /* find the event id */
105 event_id_ptr = g_hash_table_lookup(stream->event_quark_to_id,
106 (gconstpointer) (unsigned long) event);
107 /* event not found in this stream class */
108 if (!event_id_ptr) {
109 fprintf(stderr, "[error] Event ID not found in stream class\n");
110 continue;
111 }
112 event_id = (uint64_t)(unsigned long) *event_id_ptr;
113
114 /* find or create the bt_callback_chain for this event */
115 if (event_id >= bt_stream_cb->per_id_callbacks->len) {
116 g_array_set_size(bt_stream_cb->per_id_callbacks, event_id + 1);
117 }
118 bt_chain = &g_array_index(bt_stream_cb->per_id_callbacks,
119 struct bt_callback_chain, event_id);
120 if (!bt_chain->callback) {
121 bt_chain->callback = g_array_new(FALSE, TRUE,
122 sizeof(struct bt_callback));
123 }
124 } else {
125 /* callback for all events */
126 if (!iter->main_callbacks.callback) {
127 iter->main_callbacks.callback = g_array_new(FALSE, TRUE,
128 sizeof(struct bt_callback));
129 }
130 bt_chain = &iter->main_callbacks;
131 }
132
133 new_callback.private_data = private_data;
134 new_callback.flags = flags;
135 new_callback.callback = callback;
136 new_callback.depends = depends;
137 new_callback.weak_depends = weak_depends;
138 new_callback.provides = provides;
139
140 /* TODO : take care of priority, for now just FIFO */
141 g_array_append_val(bt_chain->callback, new_callback);
142 }
143 }
144
145 return 0;
146 }
147
148 static
149 struct ctf_stream_event *extract_ctf_stream_event(struct ctf_stream *stream)
150 {
151 struct ctf_stream_declaration *stream_class = stream->stream_class;
152 struct ctf_event *event_class;
153 struct ctf_stream_event *event;
154 uint64_t id = stream->event_id;
155
156 if (id >= stream_class->events_by_id->len) {
157 fprintf(stderr, "[error] Event id %" PRIu64 " is outside range.\n", id);
158 return NULL;
159 }
160 event = g_ptr_array_index(stream->events_by_id, id);
161 if (!event) {
162 fprintf(stderr, "[error] Event id %" PRIu64 " is unknown.\n", id);
163 return NULL;
164 }
165 event_class = g_ptr_array_index(stream_class->events_by_id, id);
166 if (!event_class) {
167 fprintf(stderr, "[error] Event id %" PRIu64 " is unknown.\n", id);
168 return NULL;
169 }
170
171 return event;
172 }
173
174 void process_callbacks(struct bt_ctf_iter *iter,
175 struct ctf_stream *stream)
176 {
177 struct bt_stream_callbacks *bt_stream_cb;
178 struct bt_callback_chain *bt_chain;
179 struct bt_callback *cb;
180 int i;
181 enum bt_cb_ret ret;
182 struct bt_ctf_event ctf_data;
183
184 ctf_data.event = extract_ctf_stream_event(stream);
185 ctf_data.stream = stream;
186
187 /* process all events callback first */
188 if (iter->main_callbacks.callback) {
189 for (i = 0; i < iter->main_callbacks.callback->len; i++) {
190 cb = &g_array_index(iter->main_callbacks.callback, struct bt_callback, i);
191 if (!cb)
192 goto end;
193 ret = cb->callback(&ctf_data, cb->private_data);
194 switch (ret) {
195 case BT_CB_OK_STOP:
196 case BT_CB_ERROR_STOP:
197 goto end;
198 default:
199 break;
200 }
201 }
202 }
203
204 /* process per event callbacks */
205 bt_stream_cb = &g_array_index(iter->callbacks,
206 struct bt_stream_callbacks, stream->stream_id);
207 if (!bt_stream_cb || !bt_stream_cb->per_id_callbacks)
208 goto end;
209
210 if (stream->event_id >= bt_stream_cb->per_id_callbacks->len)
211 goto end;
212 bt_chain = &g_array_index(bt_stream_cb->per_id_callbacks,
213 struct bt_callback_chain, stream->event_id);
214 if (!bt_chain || !bt_chain->callback)
215 goto end;
216
217 for (i = 0; i < bt_chain->callback->len; i++) {
218 cb = &g_array_index(bt_chain->callback, struct bt_callback, i);
219 if (!cb)
220 goto end;
221 ret = cb->callback(&ctf_data, cb->private_data);
222 switch (ret) {
223 case BT_CB_OK_STOP:
224 case BT_CB_ERROR_STOP:
225 goto end;
226 default:
227 break;
228 }
229 }
230
231 end:
232 return;
233 }
This page took 0.059244 seconds and 3 git commands to generate.