Implement the trimmer plug-in
[babeltrace.git] / plugins / trimmer / iterator.c
1 /*
2 * iterator.c
3 *
4 * Babeltrace Trace Trimmer Iterator
5 *
6 * Copyright 2016 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 #include "trimmer.h"
30 #include "iterator.h"
31 #include <babeltrace/plugin/notification/iterator.h>
32 #include <babeltrace/plugin/notification/notification.h>
33 #include <babeltrace/plugin/notification/event.h>
34 #include <babeltrace/plugin/notification/stream.h>
35 #include <babeltrace/plugin/notification/packet.h>
36 #include <babeltrace/plugin/filter.h>
37 #include <babeltrace/ctf-ir/event.h>
38 #include <babeltrace/ctf-ir/stream.h>
39 #include <babeltrace/ctf-ir/stream-class.h>
40 #include <babeltrace/ctf-ir/clock.h>
41 #include <babeltrace/ctf-ir/packet.h>
42 #include <babeltrace/ctf-ir/trace.h>
43 #include <assert.h>
44
45 static
46 void trimmer_iterator_destroy(struct bt_notification_iterator *it)
47 {
48 struct trimmer_iterator *it_data;
49
50 it_data = bt_notification_iterator_get_private_data(it);
51 assert(it_data);
52
53 if (it_data->input_iterator_group) {
54 g_ptr_array_free(it_data->input_iterator_group, TRUE);
55 }
56 bt_put(it_data->current_notification);
57 if (it_data->stream_to_packet_start_notification) {
58 g_hash_table_destroy(it_data->stream_to_packet_start_notification);
59 }
60 g_free(it_data);
61 }
62
63 BT_HIDDEN
64 enum bt_component_status trimmer_iterator_init(struct bt_component *component,
65 struct bt_notification_iterator *iterator)
66 {
67 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
68 enum bt_notification_iterator_status it_ret;
69 struct trimmer_iterator *it_data = g_new0(struct trimmer_iterator, 1);
70
71 if (!it_data) {
72 ret = BT_COMPONENT_STATUS_NOMEM;
73 goto end;
74 }
75
76 /* FIXME init trimmer_iterator */
77 it_ret = bt_notification_iterator_set_private_data(iterator, it_data);
78 if (it_ret) {
79 goto end;
80 }
81
82 it_ret = bt_notification_iterator_set_destroy_cb(iterator,
83 trimmer_iterator_destroy);
84 if (it_ret) {
85 ret = BT_COMPONENT_STATUS_ERROR;
86 goto end;
87 }
88
89 it_ret = bt_notification_iterator_set_next_cb(iterator,
90 trimmer_iterator_next);
91 if (it_ret) {
92 ret = BT_COMPONENT_STATUS_ERROR;
93 goto end;
94 }
95
96 it_ret = bt_notification_iterator_set_get_cb(iterator,
97 trimmer_iterator_get);
98 if (it_ret) {
99 ret = BT_COMPONENT_STATUS_ERROR;
100 goto end;
101 }
102
103 it_ret = bt_notification_iterator_set_seek_time_cb(iterator,
104 trimmer_iterator_seek_time);
105 if (it_ret) {
106 ret = BT_COMPONENT_STATUS_ERROR;
107 goto end;
108 }
109 end:
110 return ret;
111 }
112
113 BT_HIDDEN
114 struct bt_notification *trimmer_iterator_get(
115 struct bt_notification_iterator *iterator)
116 {
117 struct trimmer_iterator *trim_it;
118
119 trim_it = bt_notification_iterator_get_private_data(iterator);
120 assert(trim_it);
121
122 if (!trim_it->current_notification) {
123 enum bt_notification_iterator_status it_ret;
124
125 it_ret = trimmer_iterator_next(iterator);
126 if (it_ret) {
127 goto end;
128 }
129 }
130 end:
131 return bt_get(trim_it->current_notification);
132 }
133
134 /*
135 * Remove me. This is a temporary work-around due to our inhability to use
136 * libbabeltrace-ctf from libbabeltrace-plugin.
137 */
138 static
139 struct bt_ctf_stream *internal_bt_notification_get_stream(
140 struct bt_notification *notification)
141 {
142 struct bt_ctf_stream *stream = NULL;
143
144 assert(notification);
145 switch (bt_notification_get_type(notification)) {
146 case BT_NOTIFICATION_TYPE_EVENT:
147 {
148 struct bt_ctf_event *event;
149
150 event = bt_notification_event_get_event(notification);
151 stream = bt_ctf_event_get_stream(event);
152 bt_put(event);
153 break;
154 }
155 case BT_NOTIFICATION_TYPE_PACKET_START:
156 {
157 struct bt_ctf_packet *packet;
158
159 packet = bt_notification_packet_start_get_packet(notification);
160 stream = bt_ctf_packet_get_stream(packet);
161 bt_put(packet);
162 break;
163 }
164 case BT_NOTIFICATION_TYPE_PACKET_END:
165 {
166 struct bt_ctf_packet *packet;
167
168 packet = bt_notification_packet_end_get_packet(notification);
169 stream = bt_ctf_packet_get_stream(packet);
170 bt_put(packet);
171 break;
172 }
173 case BT_NOTIFICATION_TYPE_STREAM_END:
174 stream = bt_notification_stream_end_get_stream(notification);
175 break;
176 default:
177 goto end;
178 }
179 end:
180 return stream;
181 }
182
183 /* Return true if the notification should be forwarded. */
184 static
185 bool evaluate_notification(struct bt_notification *notification,
186 struct trimmer *trimmer, struct trimmer_iterator *it)
187 {
188 bool ret = true;
189 struct bt_ctf_clock *clock = NULL;
190 enum bt_notification_type type;
191 struct bt_ctf_trace *trace = NULL;
192 struct bt_ctf_stream *stream = NULL;
193 struct bt_ctf_stream_class *stream_class = NULL;
194 struct bt_ctf_clock_value *clock_value = NULL;
195
196 stream = internal_bt_notification_get_stream(notification);
197 if (!stream) {
198 goto end;
199 }
200
201 stream_class = bt_ctf_stream_get_class(stream);
202 assert(stream_class);
203 trace = bt_ctf_stream_class_get_trace(stream_class);
204 assert(trace);
205
206 type = bt_notification_get_type(notification);
207 switch (type) {
208 case BT_NOTIFICATION_TYPE_EVENT:
209 {
210 int64_t ts;
211 int clock_ret;
212 struct bt_ctf_event *event;
213
214 clock = bt_ctf_trace_get_clock(trace, 0);
215 if (!clock) {
216 goto end;
217 }
218
219 event = bt_notification_event_get_event(notification);
220 assert(event);
221 clock_value = bt_ctf_event_get_clock_value(event, clock);
222 if (!clock_value) {
223 printf_error("Failed to retrieve clock value\n");
224 bt_put(event);
225 goto end;
226 }
227
228 clock_ret = bt_ctf_clock_value_get_value_ns_from_epoch(
229 clock_value, &ts);
230 if (clock_ret) {
231 printf_error("Failed to retrieve clock value timestamp\n");
232 goto end;
233 }
234
235 if (trimmer->begin.set && ts < trimmer->begin.value) {
236 ret = false;
237 }
238 if (trimmer->end.set && ts > trimmer->end.value) {
239 ret = false;
240 }
241 break;
242 }
243 default:
244 break;
245 }
246 end:
247 bt_put(clock);
248 bt_put(trace);
249 bt_put(stream);
250 bt_put(clock_value);
251 return ret;
252 }
253
254 BT_HIDDEN
255 enum bt_notification_iterator_status trimmer_iterator_next(
256 struct bt_notification_iterator *iterator)
257 {
258 struct trimmer_iterator *trim_it = NULL;
259 struct bt_component *component = NULL;
260 struct trimmer *trimmer = NULL;
261 struct bt_notification_iterator *source_it = NULL;
262 enum bt_notification_iterator_status ret =
263 BT_NOTIFICATION_ITERATOR_STATUS_OK;;
264 enum bt_component_status component_ret;
265 bool event_in_range = false;
266
267 trim_it = bt_notification_iterator_get_private_data(iterator);
268 assert(trim_it);
269
270 component = bt_notification_iterator_get_component(iterator);
271 assert(component);
272 trimmer = bt_component_get_private_data(component);
273 assert(trimmer);
274
275 /* FIXME, should handle input iterator groups. */
276 component_ret = bt_component_filter_get_input_iterator(component, 0,
277 &source_it);
278 assert((component_ret == BT_COMPONENT_STATUS_OK) && source_it);
279
280 while (!event_in_range) {
281 struct bt_notification *notification;
282
283 ret = bt_notification_iterator_next(source_it);
284 if (ret != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
285 goto end;
286 }
287
288 notification = bt_notification_iterator_get_notification(
289 source_it);
290 if (!notification) {
291 ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
292 goto end;
293 }
294
295 event_in_range = evaluate_notification(notification, trimmer,
296 trim_it);
297 if (event_in_range) {
298 BT_MOVE(trim_it->current_notification, notification);
299 } else {
300 bt_put(notification);
301 }
302 }
303 end:
304 bt_put(source_it);
305 bt_put(component);
306 return ret;
307 }
308
309 BT_HIDDEN
310 enum bt_notification_iterator_status trimmer_iterator_seek_time(
311 struct bt_notification_iterator *iterator, int64_t time)
312 {
313 enum bt_notification_iterator_status ret;
314
315 ret = BT_NOTIFICATION_ITERATOR_STATUS_OK;
316 end:
317 return ret;
318 }
This page took 0.042565 seconds and 5 git commands to generate.