Do not use `bool` type; use new `bt_bool` instead
[babeltrace.git] / plugins / utils / trimmer / trimmer.c
CommitLineData
cab3f160
JG
1/*
2 * trimmer.c
3 *
4 * Babeltrace Trace Trimmer
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
33b34c43 29#include <babeltrace/plugin/plugin-dev.h>
b2e0c907
PP
30#include <babeltrace/graph/component.h>
31#include <babeltrace/graph/private-component.h>
32#include <babeltrace/graph/component-filter.h>
33#include <babeltrace/graph/notification.h>
34#include <babeltrace/graph/notification-iterator.h>
35#include <babeltrace/graph/private-notification-iterator.h>
b9d103be 36#include <babeltrace/graph/private-component-filter.h>
b2e0c907 37#include <babeltrace/graph/notification-event.h>
7d61fa8e 38#include <plugins-common.h>
cab3f160
JG
39#include "trimmer.h"
40#include "iterator.h"
44d3cbf0 41#include <assert.h>
cab3f160
JG
42
43static
44void destroy_trimmer_data(struct trimmer *trimmer)
45{
46 g_free(trimmer);
47}
48
49static
50struct trimmer *create_trimmer_data(void)
51{
52 struct trimmer *trimmer;
53
54 trimmer = g_new0(struct trimmer, 1);
55 if (!trimmer) {
56 goto end;
57 }
58end:
59 return trimmer;
60}
61
64cadc66 62void finalize_trimmer(struct bt_private_component *component)
cab3f160 63{
890882ef 64 void *data = bt_private_component_get_user_data(component);
cab3f160
JG
65
66 destroy_trimmer_data(data);
67}
68
528debdf
MD
69/*
70 * Parses a timestamp, figuring out its format.
71 *
72 * Returns a negative value if anything goes wrong.
73 *
74 * Expected formats:
75 *
76 * YYYY-MM-DD hh:mm:ss.ns
77 * hh:mm:ss.ns
78 * -ss.ns
79 * ss.ns
80 * YYYY-MM-DD hh:mm:ss
81 * hh:mm:ss
82 * -ss
83 * ss
84 */
44d3cbf0 85static
c6dedfd4 86int timestamp_from_arg(const char *arg, struct trimmer *trimmer,
c55a9f58 87 struct trimmer_bound *result_bound, bt_bool gmt)
528debdf
MD
88{
89 int ret;
90 int64_t value;
91 unsigned int year, month, day, hh, mm, ss, ns;
92
93 /* YYYY-MM-DD hh:mm:ss.ns */
94 ret = sscanf(arg, "%u-%u-%u %u:%u:%u.%u",
95 &year, &month, &day, &hh, &mm, &ss, &ns);
96 if (ret == 7) {
97 struct tm tm = {
98 .tm_sec = ss,
99 .tm_min = mm,
100 .tm_hour = hh,
101 .tm_mday = day,
102 .tm_mon = month - 1,
103 .tm_year = year - 1900,
104 .tm_isdst = -1,
105 };
106 time_t result;
107
108 if (gmt) {
109 result = timegm(&tm);
110 if (result < 0) {
111 return -1;
112 }
113 } else {
114 result = mktime(&tm);
115 if (result < 0) {
116 return -1;
117 }
118 }
119 value = (int64_t) result;
120 value *= NSEC_PER_SEC;
121 value += ns;
c6dedfd4
MD
122 if (!trimmer->date) {
123 trimmer->year = year;
124 trimmer->month = month;
125 trimmer->day = day;
126 trimmer->date = true;
127 }
528debdf
MD
128 goto set;
129 }
130 /* hh:mm:ss.ns */
131 ret = sscanf(arg, "%u:%u:%u.%u",
132 &hh, &mm, &ss, &ns);
133 if (ret == 4) {
c6dedfd4
MD
134 if (!trimmer->date) {
135 /* We don't know which day until we get an event. */
136 result_bound->lazy_values.hh = hh;
137 result_bound->lazy_values.mm = mm;
138 result_bound->lazy_values.ss = ss;
139 result_bound->lazy_values.ns = ns;
140 result_bound->lazy_values.gmt = gmt;
141 goto lazy;
142 } else {
143 struct tm tm = {
144 .tm_sec = ss,
145 .tm_min = mm,
146 .tm_hour = hh,
147 .tm_mday = trimmer->day,
148 .tm_mon = trimmer->month - 1,
149 .tm_year = trimmer->year - 1900,
150 .tm_isdst = -1,
151 };
152 time_t result;
153
154 if (gmt) {
155 result = timegm(&tm);
156 if (result < 0) {
157 return -1;
158 }
159 } else {
160 result = mktime(&tm);
161 if (result < 0) {
162 return -1;
163 }
164 }
165 value = (int64_t) result;
166 value *= NSEC_PER_SEC;
167 value += ns;
168 goto set;
169 }
528debdf
MD
170 }
171 /* -ss.ns */
172 ret = sscanf(arg, "-%u.%u",
173 &ss, &ns);
174 if (ret == 2) {
175 value = -ss * NSEC_PER_SEC;
176 value -= ns;
177 goto set;
178 }
179 /* ss.ns */
180 ret = sscanf(arg, "%u.%u",
181 &ss, &ns);
182 if (ret == 2) {
183 value = ss * NSEC_PER_SEC;
184 value += ns;
185 goto set;
186 }
187
188 /* YYYY-MM-DD hh:mm:ss */
189 ret = sscanf(arg, "%u-%u-%u %u:%u:%u",
190 &year, &month, &day, &hh, &mm, &ss);
191 if (ret == 6) {
192 struct tm tm = {
193 .tm_sec = ss,
194 .tm_min = mm,
195 .tm_hour = hh,
196 .tm_mday = day,
197 .tm_mon = month - 1,
198 .tm_year = year - 1900,
199 .tm_isdst = -1,
200 };
201
202 if (gmt) {
203 value = timegm(&tm);
204 if (value < 0) {
205 return -1;
206 }
207 } else {
208 value = mktime(&tm);
209 if (value < 0) {
210 return -1;
211 }
212 }
213 value *= NSEC_PER_SEC;
c6dedfd4
MD
214 if (!trimmer->date) {
215 trimmer->year = year;
216 trimmer->month = month;
217 trimmer->day = day;
218 trimmer->date = true;
219 }
528debdf
MD
220 goto set;
221 }
222 /* hh:mm:ss */
223 ret = sscanf(arg, "%u:%u:%u",
224 &hh, &mm, &ss);
225 if (ret == 3) {
c6dedfd4
MD
226 if (!trimmer->date) {
227 /* We don't know which day until we get an event. */
228 result_bound->lazy_values.hh = hh;
229 result_bound->lazy_values.mm = mm;
230 result_bound->lazy_values.ss = ss;
231 result_bound->lazy_values.ns = 0;
232 result_bound->lazy_values.gmt = gmt;
233 goto lazy;
234 } else {
235 struct tm tm = {
236 .tm_sec = ss,
237 .tm_min = mm,
238 .tm_hour = hh,
239 .tm_mday = trimmer->day,
240 .tm_mon = trimmer->month - 1,
241 .tm_year = trimmer->year - 1900,
242 .tm_isdst = -1,
243 };
244 time_t result;
245
246 if (gmt) {
247 result = timegm(&tm);
248 if (result < 0) {
249 return -1;
250 }
251 } else {
252 result = mktime(&tm);
253 if (result < 0) {
254 return -1;
255 }
256 }
257 value = (int64_t) result;
258 value *= NSEC_PER_SEC;
259 goto set;
260 }
528debdf
MD
261 }
262 /* -ss */
263 ret = sscanf(arg, "-%u",
264 &ss);
265 if (ret == 1) {
266 value = -ss * NSEC_PER_SEC;
267 goto set;
268 }
269 /* ss */
270 ret = sscanf(arg, "%u",
271 &ss);
272 if (ret == 1) {
273 value = ss * NSEC_PER_SEC;
274 goto set;
275 }
276
277 /* Not found. */
278 return -1;
279
280set:
281 result_bound->value = value;
282 result_bound->set = true;
283 return 0;
284
285lazy:
286 result_bound->lazy = true;
287 return 0;
288}
289
290static
890882ef
PP
291enum bt_component_status init_from_params(struct trimmer *trimmer,
292 struct bt_value *params)
44d3cbf0
JG
293{
294 struct bt_value *value = NULL;
c55a9f58 295 bt_bool gmt = BT_FALSE;
528debdf 296 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
44d3cbf0
JG
297
298 assert(params);
299
528debdf
MD
300 value = bt_value_map_get(params, "clock-gmt");
301 if (value) {
44d3cbf0
JG
302 enum bt_value_status value_ret;
303
528debdf
MD
304 value_ret = bt_value_bool_get(value, &gmt);
305 if (value_ret) {
306 ret = BT_COMPONENT_STATUS_INVALID;
55595636 307 printf_error("Failed to retrieve clock-gmt value. Expecting a boolean");
44d3cbf0
JG
308 }
309 }
310 bt_put(value);
528debdf
MD
311 if (ret != BT_COMPONENT_STATUS_OK) {
312 goto end;
313 }
314
315 value = bt_value_map_get(params, "begin");
316 if (value) {
44d3cbf0 317 enum bt_value_status value_ret;
528debdf 318 const char *str;
44d3cbf0 319
528debdf
MD
320 value_ret = bt_value_string_get(value, &str);
321 if (value_ret || timestamp_from_arg(str,
c6dedfd4 322 trimmer, &trimmer->begin, gmt)) {
528debdf 323 ret = BT_COMPONENT_STATUS_INVALID;
55595636 324 printf_error("Failed to retrieve begin value. Expecting a timestamp string");
44d3cbf0
JG
325 }
326 }
327 bt_put(value);
528debdf
MD
328 if (ret != BT_COMPONENT_STATUS_OK) {
329 goto end;
330 }
331
332 value = bt_value_map_get(params, "end");
333 if (value) {
334 enum bt_value_status value_ret;
335 const char *str;
336
337 value_ret = bt_value_string_get(value, &str);
338 if (value_ret || timestamp_from_arg(str,
c6dedfd4 339 trimmer, &trimmer->end, gmt)) {
528debdf 340 ret = BT_COMPONENT_STATUS_INVALID;
55595636 341 printf_error("Failed to retrieve end value. Expecting a timestamp string");
528debdf
MD
342 }
343 }
344 bt_put(value);
345end:
55595636
MD
346 if (trimmer->begin.set && trimmer->end.set) {
347 if (trimmer->begin.value > trimmer->end.value) {
348 printf_error("Unexpected: time range begin value is above end value");
349 ret = BT_COMPONENT_STATUS_INVALID;
350 }
351 }
528debdf 352 return ret;
44d3cbf0
JG
353}
354
cab3f160 355enum bt_component_status trimmer_component_init(
890882ef 356 struct bt_private_component *component, struct bt_value *params,
7d61fa8e 357 UNUSED_VAR void *init_method_data)
cab3f160
JG
358{
359 enum bt_component_status ret;
360 struct trimmer *trimmer = create_trimmer_data();
b9d103be 361 struct bt_private_port *priv_port = NULL;
cab3f160
JG
362
363 if (!trimmer) {
364 ret = BT_COMPONENT_STATUS_NOMEM;
365 goto end;
366 }
367
b9d103be
PP
368 /* Create input and output ports */
369 priv_port = bt_private_component_filter_add_input_private_port(
370 component, "in", NULL);
371 if (!priv_port) {
372 goto error;
373 }
374
375 bt_put(priv_port);
376 priv_port = bt_private_component_filter_add_output_private_port(
377 component, "out", NULL);
378 if (!priv_port) {
379 goto error;
380 }
381
890882ef 382 ret = bt_private_component_set_user_data(component, trimmer);
cab3f160
JG
383 if (ret != BT_COMPONENT_STATUS_OK) {
384 goto error;
385 }
386
528debdf 387 ret = init_from_params(trimmer, params);
cab3f160 388end:
b9d103be 389 bt_put(priv_port);
cab3f160
JG
390 return ret;
391error:
392 destroy_trimmer_data(trimmer);
b9d103be 393 ret = BT_COMPONENT_STATUS_ERROR;
cab3f160
JG
394 return ret;
395}
This page took 0.044538 seconds and 4 git commands to generate.