X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=formats%2Fctf%2Fctf.c;h=8d617bcd620f66b8576a7a40ad2dd01f9f89ad44;hp=03312f59303bb4ced8691bec3f1c2fd82bac1acc;hb=d6425aaf6026d168a695268c4aa7539956c0d0ca;hpb=3394d22e104e2f6511b656773ef4e74506842f3e diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index 03312f59..8d617bcd 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -52,16 +52,25 @@ #define min(a, b) (((a) < (b)) ? (a) : (b)) #endif +#define NSEC_PER_SEC 1000000000ULL + +int opt_clock_raw, + opt_clock_seconds, + opt_clock_date, + opt_clock_gmt; + +uint64_t opt_clock_offset; + extern int yydebug; static -struct trace_descriptor *ctf_open_trace(const char *collection_path, const char *path, int flags, - void (*move_pos_slow)(struct ctf_stream_pos *pos, size_t offset, +struct trace_descriptor *ctf_open_trace(const char *path, int flags, + void (*move_pos_slow)(struct stream_pos *pos, size_t offset, int whence), FILE *metadata_fp); static struct trace_descriptor *ctf_open_mmap_trace( struct mmap_stream_list *mmap_list, - void (*move_pos_slow)(struct ctf_stream_pos *pos, size_t offset, int whence), + void (*move_pos_slow)(struct stream_pos *pos, size_t offset, int whence), FILE *metadata_fp); static @@ -98,6 +107,9 @@ struct format ctf_format = { .close_trace = ctf_close_trace, }; +/* + * Update stream current timestamp, keep at clock frequency. + */ static void ctf_update_timestamp(struct ctf_stream *stream, struct definition_integer *integer_definition) @@ -121,9 +133,86 @@ void ctf_update_timestamp(struct ctf_stream *stream, updateval = stream->timestamp; updateval &= ~((1ULL << integer_declaration->len) - 1); updateval += newval; + stream->prev_timestamp = stream->timestamp; stream->timestamp = updateval; } +/* + * Print timestamp, rescaling clock frequency to nanoseconds and + * applying offsets as needed (unix time). + */ +void ctf_print_timestamp(FILE *fp, + struct ctf_stream *stream, + uint64_t timestamp) +{ + uint64_t ts_sec = 0, ts_nsec; + struct ctf_trace *trace = stream->stream_class->trace; + struct trace_collection *tc = trace->collection; + uint64_t tc_offset = tc->single_clock_offset_avg; + + if (stream->current_clock->freq == 1000000000ULL) { + ts_nsec = timestamp; + } else { + ts_nsec = (uint64_t) ((double) timestamp * 1000000000.0 + / (double) stream->current_clock->freq); + } + + /* Add offsets */ + if (!opt_clock_raw) { + ts_nsec += tc_offset; + } + ts_sec += opt_clock_offset; + + ts_sec += ts_nsec / NSEC_PER_SEC; + ts_nsec = ts_nsec % NSEC_PER_SEC; + + if (!opt_clock_seconds) { + struct tm tm; + time_t time_s = (time_t) ts_sec; + + if (!opt_clock_gmt) { + 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) { + 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(fp, "%s", timestr); + } + /* 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); + goto end; + } +seconds: + fprintf(fp, "%3" PRIu64 ".%09" PRIu64, + ts_sec, ts_nsec); + +end: + return; +} + static int ctf_read_event(struct stream_pos *ppos, struct ctf_stream *stream) { @@ -140,6 +229,11 @@ int ctf_read_event(struct stream_pos *ppos, struct ctf_stream *stream) ctf_pos_get_event(pos); + /* save the current position as a restore point */ + pos->last_offset = pos->offset; + /* we just read the event, it is consumed when used by the caller */ + stream->consumed = 0; + /* * This is the EOF check after we've advanced the position in * ctf_pos_get_event. @@ -317,7 +411,7 @@ void ctf_init_pos(struct ctf_stream_pos *pos, int fd, int open_flags) pos->parent.rw_table = write_dispatch_table; pos->parent.event_cb = ctf_write_event; if (fd >= 0) - ctf_move_pos_slow(pos, 0, SEEK_SET); /* position for write */ + ctf_move_pos_slow(&pos->parent, 0, SEEK_SET); /* position for write */ break; default: assert(0); @@ -342,8 +436,10 @@ void ctf_fini_pos(struct ctf_stream_pos *pos) (void) g_array_free(pos->packet_index, TRUE); } -void ctf_move_pos_slow(struct ctf_stream_pos *pos, size_t offset, int whence) +void ctf_move_pos_slow(struct stream_pos *stream_pos, size_t offset, int whence) { + struct ctf_stream_pos *pos = + container_of(stream_pos, struct ctf_stream_pos, parent); struct ctf_file_stream *file_stream = container_of(pos, struct ctf_file_stream, pos); int ret; @@ -392,20 +488,61 @@ void ctf_move_pos_slow(struct ctf_stream_pos *pos, size_t offset, int whence) read_next_packet: switch (whence) { case SEEK_CUR: - if (pos->offset == EOF) + { + uint32_t events_discarded_diff; + + if (pos->offset == EOF) { return; + } + /* For printing discarded event count */ + index = &g_array_index(pos->packet_index, + struct packet_index, pos->cur_index); + events_discarded_diff = index->events_discarded; + file_stream->parent.prev_timestamp_end = + index->timestamp_end; + if (pos->cur_index > 0) { + index = &g_array_index(pos->packet_index, + struct packet_index, + pos->cur_index - 1); + events_discarded_diff -= index->events_discarded; + } + file_stream->parent.events_discarded = events_discarded_diff; + file_stream->parent.prev_timestamp = file_stream->parent.timestamp; /* The reader will expect us to skip padding */ assert(pos->offset + offset == pos->content_size); ++pos->cur_index; break; + } case SEEK_SET: - assert(offset == 0); /* only seek supported for now */ - pos->cur_index = 0; + if (offset == 0) + pos->cur_index = 0; + file_stream->parent.prev_timestamp = 0; + file_stream->parent.prev_timestamp_end = 0; break; default: assert(0); } if (pos->cur_index >= pos->packet_index->len) { + /* + * When a stream reaches the end of the + * file, we need to show the number of + * events discarded ourselves, because + * there is no next event scheduled to + * be printed in the output. + */ + if (file_stream->parent.events_discarded) { + fflush(stdout); + fprintf(stderr, "[warning] Tracer discarded %d events at end of stream between [", + file_stream->parent.events_discarded); + ctf_print_timestamp(stderr, &file_stream->parent, + file_stream->parent.prev_timestamp); + fprintf(stderr, "] and ["); + ctf_print_timestamp(stderr, &file_stream->parent, + file_stream->parent.prev_timestamp_end); + fprintf(stderr, "]. You should consider increasing the buffer size.\n"); + fflush(stderr); + file_stream->parent.events_discarded = 0; + } pos->offset = EOF; return; } @@ -633,7 +770,7 @@ int ctf_open_trace_metadata_stream_read(struct ctf_trace *td, FILE **fp, static int ctf_open_trace_metadata_read(struct ctf_trace *td, - void (*move_pos_slow)(struct ctf_stream_pos *pos, size_t offset, + void (*move_pos_slow)(struct stream_pos *pos, size_t offset, int whence), FILE *metadata_fp) { struct ctf_scanner *scanner; @@ -904,6 +1041,7 @@ int create_stream_packet_index(struct ctf_trace *td, packet_index.packet_size = 0; packet_index.timestamp_begin = 0; packet_index.timestamp_end = 0; + packet_index.events_discarded = 0; /* read and check header, set stream id (and check) */ if (file_stream->parent.trace_packet_header) { @@ -1031,6 +1169,15 @@ int create_stream_packet_index(struct ctf_trace *td, field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index); packet_index.timestamp_end = get_unsigned_int(field); } + + /* read events discarded from header */ + len_index = struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("events_discarded")); + if (len_index >= 0) { + struct definition *field; + + field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index); + packet_index.events_discarded = get_unsigned_int(field); + } } else { /* Use file size for packet size */ packet_index.content_size = filestats.st_size * CHAR_BIT; @@ -1040,14 +1187,14 @@ int create_stream_packet_index(struct ctf_trace *td, /* Validate content size and packet size values */ if (packet_index.content_size > packet_index.packet_size) { - fprintf(stderr, "[error] Content size (%zu bits) is larger than packet size (%zu bits).\n", + fprintf(stderr, "[error] Content size (%" PRIu64 " bits) is larger than packet size (%" PRIu64 " bits).\n", packet_index.content_size, packet_index.packet_size); return -EINVAL; } - if (packet_index.packet_size > (filestats.st_size - packet_index.offset) * CHAR_BIT) { - fprintf(stderr, "[error] Packet size (%zu bits) is larger than remaining file size (%zu bits).\n", - packet_index.content_size, (size_t) (filestats.st_size - packet_index.offset) * CHAR_BIT); + if (packet_index.packet_size > ((uint64_t)filestats.st_size - packet_index.offset) * CHAR_BIT) { + fprintf(stderr, "[error] Packet size (%" PRIu64 " bits) is larger than remaining file size (%" PRIu64 " bits).\n", + packet_index.content_size, ((uint64_t)filestats.st_size - packet_index.offset) * CHAR_BIT); return -EINVAL; } @@ -1061,7 +1208,7 @@ int create_stream_packet_index(struct ctf_trace *td, } /* Move pos back to beginning of file */ - ctf_move_pos_slow(pos, 0, SEEK_SET); /* position for write */ + ctf_move_pos_slow(&pos->parent, 0, SEEK_SET); /* position for write */ return 0; } @@ -1096,7 +1243,7 @@ error: */ static int ctf_open_file_stream_read(struct ctf_trace *td, const char *path, int flags, - void (*move_pos_slow)(struct ctf_stream_pos *pos, size_t offset, + void (*move_pos_slow)(struct stream_pos *pos, size_t offset, int whence)) { int ret; @@ -1121,6 +1268,10 @@ int ctf_open_file_stream_read(struct ctf_trace *td, const char *path, int flags, ret = create_trace_definitions(td, &file_stream->parent); if (ret) goto error_def; + /* + * For now, only a single slock is supported. + */ + file_stream->parent.current_clock = td->single_clock; ret = create_stream_packet_index(td, file_stream); if (ret) goto error_index; @@ -1140,106 +1291,16 @@ error: return ret; } -static void -init_domain_name(struct ctf_trace *td) -{ - char *start, *end; - - start = td->path + strlen(td->collection_path); - while (start[0] == '/') - start++; /* skip / */ - end = strchr(start, '/'); - if (!end) - end = start + strlen(start); - memcpy(td->domain, start, end - start); - td->domain[end - start] = '\0'; -} - -static void -init_proc_name(struct ctf_trace *td) -{ - char buf[PATH_MAX]; - char *start, *end; - - if (td->domain[0] == '\0') - return; - memcpy(buf, td->path, PATH_MAX); - start = buf + strlen(td->collection_path); - while (start[0] == '/') - start++; /* skip / */ - start = strchr(start, '/'); /* get begin of domain content */ - if (!start) - return; - while (start[0] == '/') - start++; /* skip / */ - /* find last -, skips time */ - end = strrchr(start, '-'); - if (!end) - return; - *end = '\0'; - /* find previous -, skips date */ - end = strrchr(start, '-'); - if (!end) - return; - *end = '\0'; - /* find previous -, skips pid */ - end = strrchr(start, '-'); - if (!end) - return; - *end = '\0'; - - memcpy(td->procname, start, end - start); - td->procname[end - start] = '\0'; -} - -static void -init_vpid(struct ctf_trace *td) -{ - char buf[PATH_MAX]; - char *start, *end; - - if (td->domain[0] == '\0') - return; - memcpy(buf, td->path, PATH_MAX); - start = buf + strlen(td->collection_path); - while (start[0] == '/') - start++; /* skip / */ - start = strchr(start, '/'); /* get begin of domain content */ - if (!start) - return; - while (start[0] == '/') - start++; /* skip / */ - /* find last -, skips time */ - end = strrchr(start, '-'); - if (!end) - return; - *end = '\0'; - /* find previous -, skips date */ - end = strrchr(start, '-'); - if (!end) - return; - *end = '\0'; - /* find previous -, skips pid */ - start = strrchr(start, '-'); - if (!start) - return; - start++; /* skip - */ - - memcpy(td->vpid, start, end - start); - td->vpid[end - start] = '\0'; -} - static -int ctf_open_trace_read(struct ctf_trace *td, const char *collection_path, +int ctf_open_trace_read(struct ctf_trace *td, const char *path, int flags, - void (*move_pos_slow)(struct ctf_stream_pos *pos, size_t offset, + void (*move_pos_slow)(struct stream_pos *pos, size_t offset, int whence), FILE *metadata_fp) { int ret; struct dirent *dirent; struct dirent *diriter; size_t dirent_len; - char *respath, *rescolpath; td->flags = flags; @@ -1258,19 +1319,8 @@ int ctf_open_trace_read(struct ctf_trace *td, const char *collection_path, ret = -errno; goto error_dirfd; } - rescolpath = realpath(collection_path, td->collection_path); - if (!rescolpath) { - fprintf(stderr, "[error] collection path resolution failure\n"); - return -EINVAL; - } - respath = realpath(path, td->path); - if (!respath) { - fprintf(stderr, "[error] path resolution failure\n"); - return -EINVAL; - } - init_domain_name(td); - init_proc_name(td); - init_vpid(td); + strncpy(td->path, path, sizeof(td->path)); + td->path[sizeof(td->path) - 1] = '\0'; /* * Keep the metadata file separate. @@ -1326,8 +1376,8 @@ error: } static -struct trace_descriptor *ctf_open_trace(const char *collection_path, const char *path, int flags, - void (*move_pos_slow)(struct ctf_stream_pos *pos, size_t offset, +struct trace_descriptor *ctf_open_trace(const char *path, int flags, + void (*move_pos_slow)(struct stream_pos *pos, size_t offset, int whence), FILE *metadata_fp) { struct ctf_trace *td; @@ -1341,7 +1391,7 @@ struct trace_descriptor *ctf_open_trace(const char *collection_path, const char fprintf(stderr, "[error] Path missing for input CTF trace.\n"); goto error; } - ret = ctf_open_trace_read(td, collection_path, path, flags, move_pos_slow, metadata_fp); + ret = ctf_open_trace_read(td, path, flags, move_pos_slow, metadata_fp); if (ret) goto error; break; @@ -1410,7 +1460,7 @@ end: static int ctf_open_mmap_stream_read(struct ctf_trace *td, struct mmap_stream *mmap_info, - void (*move_pos_slow)(struct ctf_stream_pos *pos, size_t offset, + void (*move_pos_slow)(struct stream_pos *pos, size_t offset, int whence)) { int ret; @@ -1445,7 +1495,7 @@ error_def: int ctf_open_mmap_trace_read(struct ctf_trace *td, struct mmap_stream_list *mmap_list, - void (*move_pos_slow)(struct ctf_stream_pos *pos, size_t offset, + void (*move_pos_slow)(struct stream_pos *pos, size_t offset, int whence), FILE *metadata_fp) { @@ -1461,7 +1511,7 @@ int ctf_open_mmap_trace_read(struct ctf_trace *td, * for each stream, try to open, check magic number, and get the * stream ID to add to the right location in the stream array. */ - cds_list_for_each_entry(mmap_info, &mmap_list->head, list) { + bt_list_for_each_entry(mmap_info, &mmap_list->head, list) { ret = ctf_open_mmap_stream_read(td, mmap_info, move_pos_slow); if (ret) { fprintf(stderr, "[error] Open file mmap stream error.\n"); @@ -1478,7 +1528,7 @@ error: static struct trace_descriptor *ctf_open_mmap_trace( struct mmap_stream_list *mmap_list, - void (*move_pos_slow)(struct ctf_stream_pos *pos, size_t offset, int whence), + void (*move_pos_slow)(struct stream_pos *pos, size_t offset, int whence), FILE *metadata_fp) { struct ctf_trace *td;