From 1556a1afe8d70a3a89155ff25815e203333a93e9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Fri, 18 Nov 2016 16:42:16 -0500 Subject: [PATCH] Print timestamps in text plug-in MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérémie Galarneau --- formats/ctf/ir/clock.c | 2 +- formats/ctf/ir/event.c | 58 +++------ include/babeltrace/ctf-ir/clock.h | 2 +- include/babeltrace/ctf-ir/event-internal.h | 3 +- include/babeltrace/ctf-ir/event.h | 20 ++- plugins/ctf/common/notif-iter/notif-iter.c | 36 ++++++ plugins/text/print.c | 141 ++++++++++++++++++--- tests/lib/test_ctf_writer.c | 8 -- 8 files changed, 191 insertions(+), 79 deletions(-) diff --git a/formats/ctf/ir/clock.c b/formats/ctf/ir/clock.c index dee93c7a..4eed39c7 100644 --- a/formats/ctf/ir/clock.c +++ b/formats/ctf/ir/clock.c @@ -501,7 +501,7 @@ end: return ret; } -int bt_ctf_clock_value_ns_from_epoch(struct bt_ctf_clock_value *value, +int bt_ctf_clock_value_get_value_ns_from_epoch(struct bt_ctf_clock_value *value, int64_t *ret_value_ns) { int ret = 0; diff --git a/formats/ctf/ir/event.c b/formats/ctf/ir/event.c index beac9d48..4c1d2402 100644 --- a/formats/ctf/ir/event.c +++ b/formats/ctf/ir/event.c @@ -156,7 +156,7 @@ struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class) */ event->event_class = bt_get(event_class); event->clock_values = g_hash_table_new_full(g_direct_hash, - g_direct_equal, NULL, g_free); + g_direct_equal, bt_put, bt_put); event_header = bt_ctf_field_create(validation_output.event_header_type); if (!event_header) { @@ -282,39 +282,6 @@ end: return stream; } -struct bt_ctf_clock *bt_ctf_event_get_clock(struct bt_ctf_event *event) -{ - struct bt_ctf_clock *clock = NULL; - struct bt_ctf_event_class *event_class; - struct bt_ctf_stream_class *stream_class; - - if (!event) { - goto end; - } - - event_class = bt_ctf_event_get_class(event); - if (!event_class) { - goto end; - } - - stream_class = bt_ctf_event_class_get_stream_class(event_class); - if (!stream_class) { - goto error_put_event_class; - } - - clock = bt_ctf_stream_class_get_clock(stream_class); - if (!clock) { - goto error_put_stream_class; - } - -error_put_stream_class: - bt_put(stream_class); -error_put_event_class: - bt_put(event_class); -end: - return clock; -} - int bt_ctf_event_set_payload(struct bt_ctf_event *event, const char *name, struct bt_ctf_field *payload) @@ -600,11 +567,10 @@ void bt_ctf_event_destroy(struct bt_object *obj) g_free(event); } -uint64_t bt_ctf_event_get_clock_value(struct bt_ctf_event *event, - struct bt_ctf_clock *clock) +struct bt_ctf_clock_value *bt_ctf_event_get_clock_value( + struct bt_ctf_event *event, struct bt_ctf_clock *clock) { - uint64_t ret = -1ULL; - uint64_t *clock_value; + struct bt_ctf_clock_value *clock_value = NULL; if (!event || !clock) { goto end; @@ -615,8 +581,22 @@ uint64_t bt_ctf_event_get_clock_value(struct bt_ctf_event *event, goto end; } - ret = *clock_value; + bt_get(clock_value); +end: + return clock_value; +} + +int bt_ctf_event_set_clock_value(struct bt_ctf_event *event, + struct bt_ctf_clock *clock, struct bt_ctf_clock_value *value) +{ + int ret = 0; + + if (!event || !clock || !value || event->frozen) { + ret = -1; + goto end; + } + g_hash_table_insert(event->clock_values, bt_get(clock), bt_get(value)); end: return ret; } diff --git a/include/babeltrace/ctf-ir/clock.h b/include/babeltrace/ctf-ir/clock.h index 2bd1924b..d9e3eb06 100644 --- a/include/babeltrace/ctf-ir/clock.h +++ b/include/babeltrace/ctf-ir/clock.h @@ -257,7 +257,7 @@ extern int bt_ctf_clock_value_get_value( struct bt_ctf_clock_value *clock_value, uint64_t *raw_value); extern int bt_ctf_clock_value_get_value_ns_from_epoch( - struct bt_ctf_clock_value, int64_t *value_ns); + struct bt_ctf_clock_value *clock_value, int64_t *value_ns); #ifdef __cplusplus } diff --git a/include/babeltrace/ctf-ir/event-internal.h b/include/babeltrace/ctf-ir/event-internal.h index ed09e962..2e5175cb 100644 --- a/include/babeltrace/ctf-ir/event-internal.h +++ b/include/babeltrace/ctf-ir/event-internal.h @@ -46,7 +46,8 @@ struct bt_ctf_event { struct bt_ctf_field *stream_event_context; struct bt_ctf_field *context_payload; struct bt_ctf_field *fields_payload; - GHashTable *clock_values; /* Maps clock addresses to (uint64_t *) */ + /* Maps clock classes to bt_ctf_clock_value. */ + GHashTable *clock_values; int frozen; }; diff --git a/include/babeltrace/ctf-ir/event.h b/include/babeltrace/ctf-ir/event.h index 22ac84b1..63926ba8 100644 --- a/include/babeltrace/ctf-ir/event.h +++ b/include/babeltrace/ctf-ir/event.h @@ -38,6 +38,8 @@ extern "C" { #endif +struct bt_ctf_clock; +struct bt_ctf_clock_value; struct bt_ctf_event_class; struct bt_ctf_event; struct bt_ctf_field; @@ -82,16 +84,6 @@ extern struct bt_ctf_event_class *bt_ctf_event_get_class( extern struct bt_ctf_stream *bt_ctf_event_get_stream( struct bt_ctf_event *event); -/* - * bt_ctf_event_get_clock: get an event's associated clock. - * - * @param event Event. - * - * Returns the event's clock, NULL on error. - */ -extern struct bt_ctf_clock *bt_ctf_event_get_clock( - struct bt_ctf_event *event); - /* * bt_ctf_event_get_payload_field: get an event's payload. * @@ -248,8 +240,12 @@ extern struct bt_ctf_packet *bt_ctf_event_get_packet( extern int bt_ctf_event_set_packet(struct bt_ctf_event *event, struct bt_ctf_packet *packet); -extern uint64_t bt_ctf_event_get_clock_value(struct bt_ctf_event *event, - struct bt_ctf_clock *clock); +extern struct bt_ctf_clock_value *bt_ctf_event_get_clock_value( + struct bt_ctf_event *event, struct bt_ctf_clock *clock); + +extern int bt_ctf_event_set_clock_value( + struct bt_ctf_event *event, struct bt_ctf_clock *clock, + struct bt_ctf_clock_value *value); #ifdef __cplusplus } diff --git a/plugins/ctf/common/notif-iter/notif-iter.c b/plugins/ctf/common/notif-iter/notif-iter.c index d4bfdb1b..260d15ee 100644 --- a/plugins/ctf/common/notif-iter/notif-iter.c +++ b/plugins/ctf/common/notif-iter/notif-iter.c @@ -1758,6 +1758,37 @@ end: return selected_field_type; } +static +int set_event_clocks(struct bt_ctf_event *event, + struct bt_ctf_notif_iter *notit) +{ + int ret; + GHashTableIter iter; + struct bt_ctf_clock *clock; + uint64_t *clock_state; + + g_hash_table_iter_init(&iter, notit->clock_states); + + while (g_hash_table_iter_next(&iter, (gpointer) &clock, + (gpointer) &clock_state)) { + struct bt_ctf_clock_value *clock_value; + + clock_value = bt_ctf_clock_value_create(clock, *clock_state); + if (!clock_value) { + ret = -1; + goto end; + } + ret = bt_ctf_event_set_clock_value(event, clock, clock_value); + bt_put(clock_value); + if (ret) { + goto end; + } + } + ret = 0; +end: + return ret; +} + static struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit) { @@ -1795,6 +1826,11 @@ struct bt_ctf_event *create_event(struct bt_ctf_notif_iter *notit) goto error; } + ret = set_event_clocks(event, notit); + if (ret) { + goto error; + } + /* Associate with current packet. */ assert(notit->packet); ret = bt_ctf_event_set_packet(event, notit->packet); diff --git a/plugins/text/print.c b/plugins/text/print.c index 472c29c8..a7b67409 100644 --- a/plugins/text/print.c +++ b/plugins/text/print.c @@ -34,10 +34,13 @@ #include #include #include +#include #include #include #include "text.h" +#define NSEC_PER_SEC 1000000000LL + static inline const char *rem_(const char *str) { @@ -61,7 +64,23 @@ void print_timestamp_cycles(struct text_component *text, struct bt_ctf_clock *clock, struct bt_ctf_event *event) { - fputs("00000000000000000000", text->out); + int ret; + struct bt_ctf_clock_value *clock_value; + uint64_t cycles; + + clock_value = bt_ctf_event_get_clock_value(event, clock); + if (!clock_value) { + fputs("????????????????????", text->out); + return; + } + + ret = bt_ctf_clock_value_get_value(clock_value, &cycles); + bt_put(clock_value); + if (ret) { + fprintf(text->out, "Error"); + return; + } + fprintf(text->out, "%020" PRIu64, cycles); } static @@ -69,17 +88,103 @@ void print_timestamp_wall(struct text_component *text, struct bt_ctf_clock *clock, struct bt_ctf_event *event) { - fputs("??:??:??.?????????", text->out); -} + int ret; + struct bt_ctf_clock_value *clock_value; + int64_t ts_nsec = 0; /* add configurable offset */ + int64_t ts_sec = 0; /* add configurable offset */ + uint64_t ts_sec_abs, ts_nsec_abs; + bool is_negative; + + clock_value = bt_ctf_event_get_clock_value(event, clock); + if (!clock_value) { + fputs("??:??:??.?????????", text->out); + return; + } + + ret = bt_ctf_clock_value_get_value_ns_from_epoch(clock_value, &ts_nsec); + bt_put(clock_value); + if (ret) { + fprintf(text->out, "Error"); + return; + } + + ts_sec += ts_nsec / NSEC_PER_SEC; + ts_nsec = ts_nsec % NSEC_PER_SEC; + if (ts_sec >= 0 && ts_nsec >= 0) { + is_negative = false; + ts_sec_abs = ts_sec; + ts_nsec_abs = ts_nsec; + } else if (ts_sec > 0 && ts_nsec < 0) { + is_negative = false; + ts_sec_abs = ts_sec - 1; + ts_nsec_abs = NSEC_PER_SEC + ts_nsec; + } else if (ts_sec == 0 && ts_nsec < 0) { + is_negative = true; + ts_sec_abs = ts_sec; + ts_nsec_abs = -ts_nsec; + } else if (ts_sec < 0 && ts_nsec > 0) { + is_negative = true; + ts_sec_abs = -(ts_sec + 1); + ts_nsec_abs = NSEC_PER_SEC - ts_nsec; + } else if (ts_sec < 0 && ts_nsec == 0) { + is_negative = true; + ts_sec_abs = -ts_sec; + ts_nsec_abs = ts_nsec; + } else { /* (ts_sec < 0 && ts_nsec < 0) */ + is_negative = true; + ts_sec_abs = -ts_sec; + ts_nsec_abs = -ts_nsec; + } + + if (/*!opt_clock_seconds*/true) { + struct tm tm; + time_t time_s = (time_t) ts_sec_abs; + + if (is_negative) { + fprintf(stderr, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n"); + goto seconds; + } -static -enum bt_component_status get_event_timestamp(struct bt_ctf_event *event) -{ -/* int ret; - uint64_t value, frequency; - int64_t offset_s, offset; -*/ - return BT_COMPONENT_STATUS_OK; + if (/*!opt_clock_gmt*/true) { + struct tm *res; + + res = localtime_r(&time_s, &tm); + if (!res) { + fprintf(stderr, "[warning] Unable to get localtime.\n"); + goto seconds; + } + } else { + struct tm *res; + + res = gmtime_r(&time_s, &tm); + if (!res) { + fprintf(stderr, "[warning] Unable to get gmtime.\n"); + goto seconds; + } + } + if (/*opt_clock_date*/false) { + char timestr[26]; + size_t res; + + /* Print date and time */ + res = strftime(timestr, sizeof(timestr), + "%F ", &tm); + if (!res) { + fprintf(stderr, "[warning] Unable to print ascii time.\n"); + goto seconds; + } + fprintf(text->out, "%s", timestr); + } + /* Print time in HH:MM:SS.ns */ + fprintf(text->out, "%02d:%02d:%02d.%09" PRIu64, + tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec_abs); + goto end; + } +seconds: + fprintf(text->out, "%s%" PRId64 ".%09" PRIu64, + is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs); +end: + return; } static @@ -89,6 +194,8 @@ enum bt_component_status print_event_timestamp(struct text_component *text, bool print_names = text->options.print_header_field_names; enum bt_component_status ret = BT_COMPONENT_STATUS_OK; struct bt_ctf_stream *stream = NULL; + struct bt_ctf_stream_class *stream_class = NULL; + struct bt_ctf_trace *trace = NULL; struct bt_ctf_clock *clock = NULL; FILE *out = text->out; FILE *err = text->err; @@ -100,12 +207,10 @@ enum bt_component_status print_event_timestamp(struct text_component *text, goto end; } - clock = bt_ctf_event_get_clock(event); - if (!clock) { - /* Stream has no timestamp. */ - //puts("no_timestamp!"); - //goto end; - } + /* FIXME - error checking */ + stream_class = bt_ctf_stream_get_class(stream); + trace = bt_ctf_stream_class_get_trace(stream_class); + clock = bt_ctf_trace_get_clock(trace, 0); fputs(print_names ? "timestamp = " : "[", out); if (text->options.print_timestamp_cycles) { @@ -121,6 +226,8 @@ enum bt_component_status print_event_timestamp(struct text_component *text, end: bt_put(stream); bt_put(clock); + bt_put(stream_class); + bt_put(trace); return ret; } diff --git a/tests/lib/test_ctf_writer.c b/tests/lib/test_ctf_writer.c index c72e1d3a..04e9d996 100644 --- a/tests/lib/test_ctf_writer.c +++ b/tests/lib/test_ctf_writer.c @@ -319,7 +319,6 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class, double ret_double; int64_t ret_range_start_int64_t, ret_range_end_int64_t; uint64_t ret_range_start_uint64_t, ret_range_end_uint64_t; - struct bt_ctf_clock *ret_clock; struct bt_ctf_event_class *ret_event_class; struct bt_ctf_field *packet_context; struct bt_ctf_field *packet_context_field; @@ -560,13 +559,6 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class, ok(simple_event, "Instantiate an event containing a single integer field"); - ok(bt_ctf_event_get_clock(NULL) == NULL, - "bt_ctf_event_get_clock handles NULL correctly"); - ret_clock = bt_ctf_event_get_clock(simple_event); - ok(ret_clock == clock, - "bt_ctf_event_get_clock returns a correct clock"); - bt_put(clock); - integer_field = bt_ctf_field_create(ep_integer_field_type); bt_ctf_field_unsigned_integer_set_value(integer_field, 42); ok(bt_ctf_event_set_payload(simple_event, "integer_field", -- 2.34.1