Project

General

Profile

Bug #1350 » 0001-Handle-negative-time-and-offset-from-Epoch.patch

Heng Guo, 03/17/2022 03:04 AM

View differences:

converter/babeltrace.c
goto end;
}
errno = 0;
opt_clock_offset = strtoull(str, &endptr, 0);
opt_clock_offset = strtoll(str, &endptr, 0);
if (*endptr != '\0' || str == endptr || errno != 0) {
fprintf(stderr, "[error] Incorrect --clock-offset argument: %s\n", str);
ret = -EINVAL;
......
goto end;
}
errno = 0;
opt_clock_offset_ns = strtoull(str, &endptr, 0);
opt_clock_offset_ns = strtoll(str, &endptr, 0);
if (*endptr != '\0' || str == endptr || errno != 0) {
fprintf(stderr, "[error] Incorrect --clock-offset-ns argument: %s\n", str);
ret = -EINVAL;
formats/ctf-text/ctf-text.c
#include <unistd.h>
#include <stdlib.h>
#define NSEC_PER_SEC 1000000000ULL
#define NSEC_PER_SEC 1000000000LL
int opt_all_field_names,
opt_scope_field_names,
formats/ctf/ctf.c
*/
#define WRITE_PACKET_LEN (getpagesize() * 8 * CHAR_BIT)
#define NSEC_PER_SEC 1000000000ULL
#define NSEC_PER_SEC 1000000000LL
#define INDEX_PATH "./index/%s.idx"
......
opt_clock_date,
opt_clock_gmt;
uint64_t opt_clock_offset;
uint64_t opt_clock_offset_ns;
int64_t opt_clock_offset;
int64_t opt_clock_offset_ns;
extern int yydebug;
char *opt_debug_info_dir;
......
static
int ctf_close_trace(struct bt_trace_descriptor *descriptor);
static
uint64_t ctf_timestamp_begin(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type);
int ctf_timestamp_begin(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type,
int64_t *timestamp);
static
uint64_t ctf_timestamp_end(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type);
int ctf_timestamp_end(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type,
int64_t *timestamp);
static
int ctf_convert_index_timestamp(struct bt_trace_descriptor *tdp);
......
}
static
uint64_t ctf_timestamp_begin(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type)
int ctf_timestamp_begin(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type,
int64_t *timestamp)
{
struct ctf_trace *tin;
uint64_t begin = ULLONG_MAX;
int i, j;
int64_t begin = LLONG_MAX;
int i, j, ret;
tin = container_of(descriptor, struct ctf_trace, parent);
if (!tin)
if (!tin || !timestamp) {
ret = -EINVAL;
goto error;
}
/* for each stream_class */
for (i = 0; i < tin->streams->len; i++) {
......
parent);
stream_pos = &cfs->pos;
if (!stream_pos->packet_index)
if (!stream_pos->packet_index) {
ret = -EINVAL;
goto error;
}
if (stream_pos->packet_index->len <= 0)
continue;
......
if (index->ts_cycles.timestamp_begin < begin)
begin = index->ts_cycles.timestamp_begin;
} else {
ret = -EINVAL;
goto error;
}
}
}
return begin;
if (begin == LLONG_MAX) {
ret = -ENOENT;
goto error;
}
*timestamp = begin;
return 0;
error:
return -1ULL;
return ret;
}
static
uint64_t ctf_timestamp_end(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type)
int ctf_timestamp_end(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type,
int64_t *timestamp)
{
struct ctf_trace *tin;
uint64_t end = 0;
int i, j;
int64_t end = LLONG_MIN;
int i, j, ret;
tin = container_of(descriptor, struct ctf_trace, parent);
if (!tin)
if (!tin || !timestamp) {
ret = -EINVAL;
goto error;
}
/* for each stream_class */
for (i = 0; i < tin->streams->len; i++) {
......
parent);
stream_pos = &cfs->pos;
if (!stream_pos->packet_index)
if (!stream_pos->packet_index) {
ret = -EINVAL;
goto error;
}
if (stream_pos->packet_index->len <= 0)
continue;
......
if (index->ts_cycles.timestamp_end > end)
end = index->ts_cycles.timestamp_end;
} else {
ret = -EINVAL;
goto error;
}
}
}
return end;
if (end == LLONG_MIN) {
ret = -ENOENT;
goto error;
}
*timestamp = end;
return 0;
error:
return -1ULL;
return ret;
}
/*
......
struct ctf_stream_definition *stream,
uint64_t timestamp)
{
uint64_t ts_sec = 0, ts_nsec;
int64_t ts_sec = 0, ts_nsec;
uint64_t ts_sec_abs, ts_nsec_abs;
bool is_negative;
ts_nsec = timestamp;
......
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) {
struct tm tm;
time_t time_s = (time_t) ts_sec;
time_t time_s = (time_t) ts_sec_abs;
if (is_negative) {
fprintf(stderr, "[warning] Fallback to [sec.ns] for printing negative time value. Use --clock-seconds.\n");
goto seconds;
}
if (!opt_clock_gmt) {
struct tm *res;
......
}
/* Print time in HH:MM:SS.ns */
fprintf(fp, "%02d:%02d:%02d.%09" PRIu64,
tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec);
tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec_abs);
goto end;
}
seconds:
fprintf(fp, "%3" PRIu64 ".%09" PRIu64,
ts_sec, ts_nsec);
fprintf(fp, "%s%" PRId64 ".%09" PRIu64,
is_negative ? "-" : "", ts_sec_abs, ts_nsec_abs);
end:
return;
......
void ctf_print_timestamp(FILE *fp,
struct ctf_stream_definition *stream,
uint64_t timestamp)
int64_t timestamp)
{
if (opt_clock_cycles) {
ctf_print_timestamp_cycles(fp, stream, timestamp);
formats/ctf/events-private.h
#include <babeltrace/clock-internal.h>
static inline
uint64_t ctf_get_real_timestamp(struct ctf_stream_definition *stream,
uint64_t timestamp)
int64_t ctf_get_real_timestamp(struct ctf_stream_definition *stream,
uint64_t ts_cycles)
{
uint64_t ts_nsec;
int64_t ts_nsec;
struct ctf_trace *trace = stream->stream_class->trace;
struct trace_collection *tc = trace->parent.collection;
uint64_t tc_offset;
int64_t tc_offset;
if (tc->clock_use_offset_avg)
tc_offset = tc->single_clock_offset_avg;
else
tc_offset = clock_offset_ns(trace->parent.single_clock);
ts_nsec = clock_cycles_to_ns(stream->current_clock, timestamp);
ts_nsec = clock_cycles_to_ns(stream->current_clock, ts_cycles);
ts_nsec += tc_offset; /* Add offset */
return ts_nsec;
}
formats/ctf/events.c
return ret;
}
uint64_t bt_ctf_get_timestamp(const struct bt_ctf_event *ctf_event)
int bt_ctf_get_timestamp(const struct bt_ctf_event *ctf_event, int64_t *timestamp)
{
const struct ctf_event_definition *event;
if (!ctf_event)
return -1ULL;
if (!ctf_event || !timestamp)
return -1;
event = ctf_event->parent;
if (event && event->stream->has_timestamp)
return event->stream->real_timestamp;
*timestamp = event->stream->real_timestamp;
else
return -1ULL;
return -1;
return 0;
}
uint64_t bt_ctf_get_cycles(const struct bt_ctf_event *ctf_event)
formats/ctf/metadata/ctf-visitor-generate-io-struct.c
bt_list_for_each_entry(node, head, siblings) {
if (node->type != NODE_UNARY_EXPRESSION
|| node->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT
|| (node->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT && node->u.unary_expression.type != UNARY_SIGNED_CONSTANT)
|| node->u.unary_expression.link != UNARY_LINK_UNKNOWN
|| i != 0)
include/babeltrace/babeltrace-internal.h
GPtrArray *array; /* struct bt_trace_descriptor */
GHashTable *clocks; /* struct ctf_clock */
uint64_t single_clock_offset_avg;
uint64_t offset_first;
int64_t single_clock_offset_avg;
int64_t offset_first;
int64_t delta_offset_first_sum;
int offset_nr;
int clock_use_offset_avg;
......
opt_clock_force_correlate,
opt_debug_info_full_path;
extern uint64_t opt_clock_offset;
extern uint64_t opt_clock_offset_ns;
extern int64_t opt_clock_offset;
extern int64_t opt_clock_offset_ns;
extern int babeltrace_ctf_console_output;
extern char *opt_debug_info_dir;
extern char *opt_debug_info_target_prefix;
include/babeltrace/clock-internal.h
* mantissa.
*/
static inline
uint64_t clock_offset_ns(struct ctf_clock *clock)
int64_t clock_offset_ns(struct ctf_clock *clock)
{
return clock->offset_s * 1000000000ULL
+ clock_cycles_to_ns(clock, clock->offset);
include/babeltrace/ctf-ir/clock-internal.h
uint64_t precision;
int64_t offset_s; /* Offset in seconds */
int64_t offset; /* Offset in ticks */
uint64_t value; /* Current clock value */
int64_t value; /* Current clock value */
uuid_t uuid;
int uuid_set;
int absolute;
include/babeltrace/ctf/events.h
uint64_t bt_ctf_get_cycles(const struct bt_ctf_event *event);
/*
* bt_ctf_get_timestamp: returns the timestamp of the event offsetted
* with the system clock source (in ns) or -1ULL on error
* bt_ctf_get_timestamp: get the timestamp of the event offsetted
* with the system clock source (in ns) in *timestamp.
*
* Return 0 on success, or -1ULL on error.
*/
uint64_t bt_ctf_get_timestamp(const struct bt_ctf_event *event);
int bt_ctf_get_timestamp(const struct bt_ctf_event *event, int64_t *timestamp);
/*
* bt_ctf_get_field_list: obtain the list of fields for compound type
include/babeltrace/ctf/types.h
struct bt_stream_callbacks;
struct packet_index_time {
uint64_t timestamp_begin;
uint64_t timestamp_end;
int64_t timestamp_begin;
int64_t timestamp_end;
};
struct packet_index {
......
}
void ctf_print_timestamp(FILE *fp, struct ctf_stream_definition *stream,
uint64_t timestamp);
int64_t timestamp);
int ctf_append_trace_metadata(struct bt_trace_descriptor *tdp,
FILE *metadata_fp);
void ctf_print_discarded_lost(FILE *fp, struct ctf_stream_definition *stream);
include/babeltrace/format.h
struct bt_context *ctx);
void (*set_handle)(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle);
uint64_t (*timestamp_begin)(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type);
uint64_t (*timestamp_end)(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type);
int (*timestamp_begin)(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type,
int64_t *timestamp);
int (*timestamp_end)(struct bt_trace_descriptor *descriptor,
struct bt_trace_handle *handle, enum bt_clock_type type,
int64_t *timestamp);
int (*convert_index_timestamp)(struct bt_trace_descriptor *descriptor);
};
include/babeltrace/trace-handle-internal.h
struct bt_trace_descriptor *td;
struct bt_format *format;
char path[PATH_MAX];
uint64_t real_timestamp_begin;
uint64_t real_timestamp_end;
uint64_t cycles_timestamp_begin;
uint64_t cycles_timestamp_end;
int64_t real_timestamp_begin;
int64_t real_timestamp_end;
int64_t cycles_timestamp_begin;
int64_t cycles_timestamp_end;
};
/*
include/babeltrace/trace-handle.h
const char *bt_trace_handle_get_path(struct bt_context *ctx, int handle_id);
/*
* bt_trace_handle_get_timestamp_begin : returns the creation time (in
* nanoseconds or cycles depending on type) of the buffers of a trace
* or -1ULL on error.
* bt_trace_handle_get_timestamp_begin : get the creation time (in
* nanoseconds or cycles depending on type) of the buffers of a trace.
*
* Returns 0 on success, -1 on error.
*/
uint64_t bt_trace_handle_get_timestamp_begin(struct bt_context *ctx,
int handle_id, enum bt_clock_type type);
int bt_trace_handle_get_timestamp_begin(struct bt_context *ctx,
int handle_id, enum bt_clock_type type,
int64_t *timestamp);
/*
* bt_trace_handle_get_timestamp_end : returns the destruction timestamp
* (in nanoseconds or cycles depending on type) of the buffers of a trace
* or -1ULL on error.
* bt_trace_handle_get_timestamp_end : get the destruction time
* (in nanoseconds or cycles depending on type) of the buffers of a
* trace.
*
* Returns 0 on success, -1 on error.
*/
uint64_t bt_trace_handle_get_timestamp_end(struct bt_context *ctx,
int handle_id, enum bt_clock_type type);
int bt_trace_handle_get_timestamp_end(struct bt_context *ctx,
int handle_id, enum bt_clock_type type,
int64_t *timestamp);
/*
* bt_ctf_event_get_handle_id : get the handle id associated with an event
lib/context.c
goto error_collection_del;
}
if (fmt->timestamp_begin)
handle->real_timestamp_begin = fmt->timestamp_begin(td,
handle, BT_CLOCK_REAL);
if (fmt->timestamp_end)
handle->real_timestamp_end = fmt->timestamp_end(td, handle,
BT_CLOCK_REAL);
if (fmt->timestamp_begin)
handle->cycles_timestamp_begin = fmt->timestamp_begin(td,
handle, BT_CLOCK_CYCLES);
if (fmt->timestamp_end)
handle->cycles_timestamp_end = fmt->timestamp_end(td, handle,
BT_CLOCK_CYCLES);
if (fmt->timestamp_begin) {
ret = fmt->timestamp_begin(td, handle, BT_CLOCK_REAL,
&handle->real_timestamp_begin);
if (ret < 0 && ret != -ENOENT) {
ret = -1;
goto error_collection_del;
}
}
if (fmt->timestamp_end) {
ret = fmt->timestamp_end(td, handle, BT_CLOCK_REAL,
&handle->real_timestamp_end);
if (ret < 0 && ret != -ENOENT) {
ret = -1;
goto error_collection_del;
}
}
if (fmt->timestamp_begin) {
ret = fmt->timestamp_begin(td, handle, BT_CLOCK_CYCLES,
&handle->cycles_timestamp_begin);
if (ret < 0 && ret != -ENOENT) {
ret = -1;
goto error_collection_del;
}
}
if (fmt->timestamp_end) {
ret = fmt->timestamp_end(td, handle, BT_CLOCK_CYCLES,
&handle->cycles_timestamp_end);
if (ret < 0 && ret != -ENOENT) {
ret = -1;
goto error_collection_del;
}
}
/* Add new handle to container */
g_hash_table_insert(ctx->trace_handles,
lib/trace-handle.c
return handle->path;
}
uint64_t bt_trace_handle_get_timestamp_begin(struct bt_context *ctx,
int handle_id, enum bt_clock_type type)
int bt_trace_handle_get_timestamp_begin(struct bt_context *ctx,
int handle_id, enum bt_clock_type type,
int64_t *timestamp)
{
struct bt_trace_handle *handle;
uint64_t ret;
if (!ctx)
return -1ULL;
int ret = 0;
if (!ctx || !timestamp)
return -1;
handle = g_hash_table_lookup(ctx->trace_handles,
(gpointer) (unsigned long) handle_id);
if (!handle) {
ret = -1ULL;
ret = -1;
goto end;
}
if (type == BT_CLOCK_REAL) {
ret = handle->real_timestamp_begin;
*timestamp = handle->real_timestamp_begin;
} else if (type == BT_CLOCK_CYCLES) {
ret = handle->cycles_timestamp_begin;
*timestamp = handle->cycles_timestamp_begin;
} else {
ret = -1ULL;
ret = -1;
}
end:
return ret;
}
uint64_t bt_trace_handle_get_timestamp_end(struct bt_context *ctx,
int handle_id, enum bt_clock_type type)
int bt_trace_handle_get_timestamp_end(struct bt_context *ctx,
int handle_id, enum bt_clock_type type,
int64_t *timestamp)
{
struct bt_trace_handle *handle;
uint64_t ret;
int ret = 0;
if (!ctx)
return -1ULL;
if (!ctx || !timestamp)
return -1;
handle = g_hash_table_lookup(ctx->trace_handles,
(gpointer) (unsigned long) handle_id);
if (!handle) {
ret = -1ULL;
ret = -1;
goto end;
}
if (type == BT_CLOCK_REAL) {
ret = handle->real_timestamp_end;
*timestamp = handle->real_timestamp_end;
} else if (type == BT_CLOCK_CYCLES) {
ret = handle->cycles_timestamp_end;
*timestamp = handle->cycles_timestamp_end;
} else {
ret = -1ULL;
ret = -1;
}
end:
tests/lib/test_ctf_writer.c
#define SEQUENCE_TEST_LENGTH 10
#define PACKET_RESIZE_TEST_LENGTH 100000
static uint64_t current_time;
static int64_t current_time;
void validate_metadata(char *parser_path, char *metadata_path)
{
......
const char *clock_name = "test_clock";
const char *clock_description = "This is a test clock";
const uint64_t frequency = 1000000000;
const uint64_t offset_s = 1351530929945824323;
const uint64_t offset = 1234567;
const int64_t offset_s = 1351530929945824323;
const int64_t offset = 1234567;
const uint64_t precision = 10;
char *metadata_string;
struct bt_ctf_writer *writer;
tests/lib/test_seek.c
#include <tap/tap.h>
#include "common.h"
#define NR_TESTS 29
#define NR_TESTS 36
void run_seek_begin(char *path, uint64_t expected_begin)
{
......
struct bt_ctf_event *event;
struct bt_iter_pos newpos;
int ret;
uint64_t timestamp_begin;
uint64_t timestamp_seek_begin;
int64_t timestamp_begin;
int64_t timestamp_seek_begin;
unsigned int nr_seek_begin_test;
nr_seek_begin_test = 5;
......
ok(event, "Event valid");
/* Validate that the first timestamp is right */
timestamp_begin = bt_ctf_get_timestamp(event);
ok1(bt_ctf_get_timestamp(event, &timestamp_begin) == 0);
ok1(timestamp_begin == expected_begin);
......
ok(event, "Event valid");
timestamp_seek_begin = bt_ctf_get_timestamp(event);
ok1(bt_ctf_get_timestamp(event, &timestamp_seek_begin) == 0);
ok1(timestamp_begin == timestamp_seek_begin);
bt_context_put(ctx);
......
struct bt_ctf_event *event;
struct bt_iter_pos newpos;
int ret;
uint64_t timestamp_last;
int64_t timestamp_last;
unsigned int nr_seek_last_tests;
nr_seek_last_tests = 6;
......
ok(event, "Event valid at last position");
timestamp_last = bt_ctf_get_timestamp(event);
ok1(bt_ctf_get_timestamp(event, &timestamp_last) == 0);
ok1(timestamp_last == expected_last);
......
struct bt_ctf_event *event;
struct bt_iter_pos newpos;
int ret;
uint64_t timestamp_last;
int64_t timestamp_last;
unsigned int nr_seek_time_at_last_tests;
nr_seek_time_at_last_tests = 6;
......
ok(event, "Event valid at last position");
timestamp_last = bt_ctf_get_timestamp(event);
ok1(bt_ctf_get_timestamp(event, &timestamp_last) == 0);
ok1(timestamp_last == expected_last);
......
struct bt_ctf_event *event;
struct bt_iter_pos newpos;
int ret;
uint64_t timestamp;
int64_t timestamp;
unsigned int nr_seek_cycles_tests;
......
ok(event, "Event valid at last position");
timestamp = bt_ctf_get_timestamp(event);
ok1(bt_ctf_get_timestamp(event, &timestamp) == 0);
ok1(timestamp == expected_last);
......
ok(event, "Event valid at first position");
timestamp = bt_ctf_get_timestamp(event);
ok1(bt_ctf_get_timestamp(event, &timestamp) == 0);
ok1(timestamp == expected_begin);
......
ok(event, "Event valid at last position");
timestamp = bt_ctf_get_timestamp(event);
ok1(bt_ctf_get_timestamp(event, &timestamp) == 0);
ok1(timestamp == expected_last);
(1-1/3)