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