clock: use freq field
[babeltrace.git] / formats / ctf / ctf.c
index d4004d856b731555be744afc6481d8afe9f9d84c..80bd37869ed897f947c1b99e3f871b3d93d9692d 100644 (file)
 #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,
+struct trace_descriptor *ctf_open_trace(const char *path, int flags,
                void (*move_pos_slow)(struct ctf_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)
 {
@@ -395,24 +484,23 @@ void ctf_move_pos_slow(struct ctf_stream_pos *pos, size_t offset, int whence)
                {
                        uint32_t events_discarded_diff;
 
-                       /* Print lost event count */
+                       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;
                        }
-                       if (events_discarded_diff != 0) {
-                               fflush(stdout);
-                               fprintf(stderr, "[warning] %d events discarded by tracer. You should try using larger buffers.\n",
-                                       events_discarded_diff);
-                               fflush(stderr);
-                       }
-                       if (pos->offset == EOF)
-                               return;
+                       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;
@@ -421,11 +509,33 @@ void ctf_move_pos_slow(struct ctf_stream_pos *pos, size_t offset, int whence)
                case SEEK_SET:
                        assert(offset == 0);    /* only seek supported for now */
                        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;
                }
@@ -1151,6 +1261,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;
@@ -1170,97 +1284,8 @@ 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,
                        int whence), FILE *metadata_fp)
@@ -1269,7 +1294,6 @@ int ctf_open_trace_read(struct ctf_trace *td, const char *collection_path,
        struct dirent *dirent;
        struct dirent *diriter;
        size_t dirent_len;
-       char *respath, *rescolpath;
 
        td->flags = flags;
 
@@ -1288,19 +1312,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.
@@ -1356,7 +1369,7 @@ error:
 }
 
 static
-struct trace_descriptor *ctf_open_trace(const char *collection_path, const char *path, int flags,
+struct trace_descriptor *ctf_open_trace(const char *path, int flags,
                void (*move_pos_slow)(struct ctf_stream_pos *pos, size_t offset,
                        int whence), FILE *metadata_fp)
 {
@@ -1371,7 +1384,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;
This page took 0.026409 seconds and 4 git commands to generate.