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