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