X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=plugins%2Ftrimmer%2Ftrimmer.c;h=49be358b621d58831e242a25b37411d87bf79255;hb=6ba0b073d3cc5040234aad3ab820b7ca4022e3e9;hp=23fe713481e67676941545bfe2db5e514b90cf14;hpb=44d3cbf0a1e9a9911cb1aa511ee2f49c270e2327;p=babeltrace.git diff --git a/plugins/trimmer/trimmer.c b/plugins/trimmer/trimmer.c index 23fe7134..49be358b 100644 --- a/plugins/trimmer/trimmer.c +++ b/plugins/trimmer/trimmer.c @@ -26,12 +26,12 @@ * SOFTWARE. */ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include "trimmer.h" #include "iterator.h" #include @@ -63,37 +63,289 @@ void destroy_trimmer(struct bt_component *component) destroy_trimmer_data(data); } +/* + * Parses a timestamp, figuring out its format. + * + * Returns a negative value if anything goes wrong. + * + * Expected formats: + * + * YYYY-MM-DD hh:mm:ss.ns + * hh:mm:ss.ns + * -ss.ns + * ss.ns + * YYYY-MM-DD hh:mm:ss + * hh:mm:ss + * -ss + * ss + */ +static +int timestamp_from_arg(const char *arg, struct trimmer *trimmer, + struct trimmer_bound *result_bound, bool gmt) +{ + int ret; + int64_t value; + unsigned int year, month, day, hh, mm, ss, ns; + + /* YYYY-MM-DD hh:mm:ss.ns */ + ret = sscanf(arg, "%u-%u-%u %u:%u:%u.%u", + &year, &month, &day, &hh, &mm, &ss, &ns); + if (ret == 7) { + struct tm tm = { + .tm_sec = ss, + .tm_min = mm, + .tm_hour = hh, + .tm_mday = day, + .tm_mon = month - 1, + .tm_year = year - 1900, + .tm_isdst = -1, + }; + time_t result; + + if (gmt) { + result = timegm(&tm); + if (result < 0) { + return -1; + } + } else { + result = mktime(&tm); + if (result < 0) { + return -1; + } + } + value = (int64_t) result; + value *= NSEC_PER_SEC; + value += ns; + if (!trimmer->date) { + trimmer->year = year; + trimmer->month = month; + trimmer->day = day; + trimmer->date = true; + } + goto set; + } + /* hh:mm:ss.ns */ + ret = sscanf(arg, "%u:%u:%u.%u", + &hh, &mm, &ss, &ns); + if (ret == 4) { + if (!trimmer->date) { + /* We don't know which day until we get an event. */ + result_bound->lazy_values.hh = hh; + result_bound->lazy_values.mm = mm; + result_bound->lazy_values.ss = ss; + result_bound->lazy_values.ns = ns; + result_bound->lazy_values.gmt = gmt; + goto lazy; + } else { + struct tm tm = { + .tm_sec = ss, + .tm_min = mm, + .tm_hour = hh, + .tm_mday = trimmer->day, + .tm_mon = trimmer->month - 1, + .tm_year = trimmer->year - 1900, + .tm_isdst = -1, + }; + time_t result; + + if (gmt) { + result = timegm(&tm); + if (result < 0) { + return -1; + } + } else { + result = mktime(&tm); + if (result < 0) { + return -1; + } + } + value = (int64_t) result; + value *= NSEC_PER_SEC; + value += ns; + goto set; + } + } + /* -ss.ns */ + ret = sscanf(arg, "-%u.%u", + &ss, &ns); + if (ret == 2) { + value = -ss * NSEC_PER_SEC; + value -= ns; + goto set; + } + /* ss.ns */ + ret = sscanf(arg, "%u.%u", + &ss, &ns); + if (ret == 2) { + value = ss * NSEC_PER_SEC; + value += ns; + goto set; + } + + /* YYYY-MM-DD hh:mm:ss */ + ret = sscanf(arg, "%u-%u-%u %u:%u:%u", + &year, &month, &day, &hh, &mm, &ss); + if (ret == 6) { + struct tm tm = { + .tm_sec = ss, + .tm_min = mm, + .tm_hour = hh, + .tm_mday = day, + .tm_mon = month - 1, + .tm_year = year - 1900, + .tm_isdst = -1, + }; + + if (gmt) { + value = timegm(&tm); + if (value < 0) { + return -1; + } + } else { + value = mktime(&tm); + if (value < 0) { + return -1; + } + } + value *= NSEC_PER_SEC; + if (!trimmer->date) { + trimmer->year = year; + trimmer->month = month; + trimmer->day = day; + trimmer->date = true; + } + goto set; + } + /* hh:mm:ss */ + ret = sscanf(arg, "%u:%u:%u", + &hh, &mm, &ss); + if (ret == 3) { + if (!trimmer->date) { + /* We don't know which day until we get an event. */ + result_bound->lazy_values.hh = hh; + result_bound->lazy_values.mm = mm; + result_bound->lazy_values.ss = ss; + result_bound->lazy_values.ns = 0; + result_bound->lazy_values.gmt = gmt; + goto lazy; + } else { + struct tm tm = { + .tm_sec = ss, + .tm_min = mm, + .tm_hour = hh, + .tm_mday = trimmer->day, + .tm_mon = trimmer->month - 1, + .tm_year = trimmer->year - 1900, + .tm_isdst = -1, + }; + time_t result; + + if (gmt) { + result = timegm(&tm); + if (result < 0) { + return -1; + } + } else { + result = mktime(&tm); + if (result < 0) { + return -1; + } + } + value = (int64_t) result; + value *= NSEC_PER_SEC; + goto set; + } + } + /* -ss */ + ret = sscanf(arg, "-%u", + &ss); + if (ret == 1) { + value = -ss * NSEC_PER_SEC; + goto set; + } + /* ss */ + ret = sscanf(arg, "%u", + &ss); + if (ret == 1) { + value = ss * NSEC_PER_SEC; + goto set; + } + + /* Not found. */ + return -1; + +set: + result_bound->value = value; + result_bound->set = true; + return 0; + +lazy: + result_bound->lazy = true; + return 0; +} + static -void init_from_params(struct trimmer *trimmer, struct bt_value *params) +enum bt_component_status init_from_params(struct trimmer *trimmer, struct bt_value *params) { struct bt_value *value = NULL; + bool gmt = false; + enum bt_component_status ret = BT_COMPONENT_STATUS_OK; assert(params); - value = bt_value_map_get(params, "begin_ns_epoch"); - if (value && bt_value_is_integer(value)) { + value = bt_value_map_get(params, "clock-gmt"); + if (value) { enum bt_value_status value_ret; - value_ret = bt_value_integer_get(value, &trimmer->begin.value); - if (!value_ret) { - trimmer->begin.set = true; - } else { - printf_error("Failed to retrieve begin_ns_epoch value\n"); + value_ret = bt_value_bool_get(value, &gmt); + if (value_ret) { + ret = BT_COMPONENT_STATUS_INVALID; + printf_error("Failed to retrieve clock-gmt value. Expecting a boolean"); } } bt_put(value); - value = bt_value_map_get(params, "end_ns_epoch"); - if (value && bt_value_is_integer(value)) { + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + value = bt_value_map_get(params, "begin"); + if (value) { enum bt_value_status value_ret; + const char *str; - value_ret = bt_value_integer_get(value, &trimmer->end.value); - if (!value_ret) { - trimmer->end.set = true; - } else { - printf_error("Failed to retrieve end_ns_epoch value\n"); + value_ret = bt_value_string_get(value, &str); + if (value_ret || timestamp_from_arg(str, + trimmer, &trimmer->begin, gmt)) { + ret = BT_COMPONENT_STATUS_INVALID; + printf_error("Failed to retrieve begin value. Expecting a timestamp string"); } } bt_put(value); + if (ret != BT_COMPONENT_STATUS_OK) { + goto end; + } + + value = bt_value_map_get(params, "end"); + if (value) { + enum bt_value_status value_ret; + const char *str; + + value_ret = bt_value_string_get(value, &str); + if (value_ret || timestamp_from_arg(str, + trimmer, &trimmer->end, gmt)) { + ret = BT_COMPONENT_STATUS_INVALID; + printf_error("Failed to retrieve end value. Expecting a timestamp string"); + } + } + bt_put(value); +end: + if (trimmer->begin.set && trimmer->end.set) { + if (trimmer->begin.value > trimmer->end.value) { + printf_error("Unexpected: time range begin value is above end value"); + ret = BT_COMPONENT_STATUS_INVALID; + } + } + return ret; } enum bt_component_status trimmer_component_init( @@ -124,7 +376,7 @@ enum bt_component_status trimmer_component_init( goto error; } - init_from_params(trimmer, params); + ret = init_from_params(trimmer, params); end: return ret; error: @@ -133,13 +385,11 @@ error: } /* Initialize plug-in entry points. */ -BT_PLUGIN_NAME("utils"); +BT_PLUGIN(utils); BT_PLUGIN_DESCRIPTION("Babeltrace Trace Trimmer Plug-In."); BT_PLUGIN_AUTHOR("Jérémie Galarneau"); BT_PLUGIN_LICENSE("MIT"); - -BT_PLUGIN_COMPONENT_CLASSES_BEGIN -BT_PLUGIN_FILTER_COMPONENT_CLASS_ENTRY("trimmer", - "Ensure that trace notifications outside of a given range are filtered-out.", - trimmer_component_init) -BT_PLUGIN_COMPONENT_CLASSES_END +BT_PLUGIN_COMPONENT_CLASS(BT_COMPONENT_TYPE_FILTER, trimmer, + trimmer_component_init); +BT_PLUGIN_COMPONENT_CLASS_DESCRIPTION(BT_COMPONENT_TYPE_FILTER, trimmer, + "Ensure that trace notifications outside of a given range are filtered-out.");