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