ltt traceread: fix offsets calculation, should be per tracefile
[lttv.git] / ltt / tracefile.c
index d61f4af879f2425ef243abc63549dbdbd6e5b848..0d8a248eb859900525e528445520119247ecc485 100644 (file)
@@ -55,6 +55,8 @@
 
 /* from marker.c */
 extern long marker_update_fields_offsets(struct marker_info *info, const char *data);
+extern void marker_update_event_fields_offsets(GArray *fields_offsets,
+                                              struct marker_info *info);
 
 /* Tracefile names used in this file */
 
@@ -80,8 +82,6 @@ GQuark LTT_TRACEFILE_NAME_METADATA;
 #define PAGE_MASK (~(page_size-1))
 #define PAGE_ALIGN(addr)  (((addr)+page_size-1)&PAGE_MASK)
 
-LttTrace *father_trace = NULL;
-
 /* set the offset of the fields belonging to the event,
    need the information of the archecture */
 //void set_fields_offsets(LttTracefile *tf, LttEventType *event_type);
@@ -150,9 +150,9 @@ static int parse_trace_header(ltt_subbuffer_header_t *header,
     break;
   case 2:
     switch(header->minor_version) {
-    case 5:
+    case 6:
       {
-        struct ltt_subbuffer_header_2_5 *vheader = header;
+        struct ltt_subbuffer_header_2_6 *vheader = header;
         tf->buffer_header_size = ltt_subbuffer_header_size();
         tf->tscbits = 27;
         tf->eventbits = 5;
@@ -164,12 +164,6 @@ static int parse_trace_header(ltt_subbuffer_header_t *header,
                                          &vheader->start_freq);
           t->freq_scale = ltt_get_uint32(LTT_GET_BO(tf),
                                          &vheader->freq_scale);
-          if(father_trace) {
-            t->start_freq = father_trace->start_freq;
-            t->freq_scale = father_trace->freq_scale;
-          } else {
-            father_trace = t;
-          }
           t->start_tsc = ltt_get_uint64(LTT_GET_BO(tf),
                                         &vheader->cycle_count_begin);
           t->start_monotonic = 0;
@@ -179,10 +173,9 @@ static int parse_trace_header(ltt_subbuffer_header_t *header,
                                        &vheader->start_time_usec);
           t->start_time.tv_nsec *= 1000; /* microsec to nanosec */
 
-          t->start_time_from_tsc = ltt_time_from_uint64(
-              (double)t->start_tsc
-              * 1000000000.0 * tf->trace->freq_scale
-              / (double)t->start_freq);
+         t->start_time_from_tsc =
+                 ltt_time_from_uint64(tsc_to_uint64(t->freq_scale,
+                                 t->start_freq, t->start_tsc));
         }
       }
       break;
@@ -342,7 +335,13 @@ static gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf)
     perror("Cannot map block for tracefile");
     goto close_file;
   }
-  
+  /* Create fields offset table */
+  tf->event.fields_offsets = g_array_sized_new(FALSE, FALSE,
+                                               sizeof(struct LttField), 1);
+  if (!tf->event.fields_offsets)
+    goto close_file;
+
   return 0;
 
   /* Error */
@@ -385,6 +384,7 @@ static void ltt_tracefile_close(LttTracefile *t)
   close(t->fd);
   if (t->buf_index)
     g_array_free(t->buf_index, TRUE);
+  g_array_free(t->event.fields_offsets, TRUE);
 }
 
 /****************************************************************************
@@ -880,6 +880,8 @@ LttTrace *ltt_trace_open(const gchar *pathname)
   g_assert(!ret);
 
   t->num_cpu = group->len;
+  t->drift = 1.;
+  t->offset = 0.;
   
   //ret = allocate_marker_data(t);
   //if (ret)
@@ -1162,28 +1164,22 @@ fail:
   return 1;
 }
 
+/*
+ * Convert a value in "TSC scale" to a value in nanoseconds
+ */
+guint64 tsc_to_uint64(guint32 freq_scale, uint64_t start_freq, guint64 tsc)
+{
+       return (double) tsc * NANOSECONDS_PER_SECOND * freq_scale / start_freq;
+}
+
 /* Given a TSC value, return the LttTime (seconds,nanoseconds) it
  * corresponds to.
  */
-
 LttTime ltt_interpolate_time_from_tsc(LttTracefile *tf, guint64 tsc)
 {
-  LttTime time;
-  
-  if(tsc > tf->trace->start_tsc) {
-    time = ltt_time_from_uint64(
-        (double)(tsc - tf->trace->start_tsc) 
-                                    * 1000000000.0 * tf->trace->freq_scale
-                                    / (double)tf->trace->start_freq);
-    time = ltt_time_add(tf->trace->start_time_from_tsc, time);
-  } else {
-    time = ltt_time_from_uint64(
-        (double)(tf->trace->start_tsc - tsc)
-                                    * 1000000000.0 * tf->trace->freq_scale
-                                    / (double)tf->trace->start_freq);
-    time = ltt_time_sub(tf->trace->start_time_from_tsc, time);
-  }
-  return time;
+       return ltt_time_from_uint64(tsc_to_uint64(tf->trace->freq_scale,
+                       tf->trace->start_freq, tf->trace->drift * tsc +
+                       tf->trace->offset));
 }
 
 /* Calculate the real event time based on the buffer boundaries */
@@ -1606,8 +1602,9 @@ void ltt_update_event_size(LttTracefile *tf)
     if (info->size != -1)
       size = info->size;
     else
-      size = marker_update_fields_offsets(marker_get_info_from_id(tf->mdata,
-                                   tf->event.event_id), tf->event.data);
+      size = marker_update_fields_offsets(info, tf->event.data);
+    /* Update per-tracefile offsets */
+    marker_update_event_fields_offsets(tf->event.fields_offsets, info);
   }
 
   tf->event.data_size = size;
@@ -1803,3 +1800,138 @@ static __attribute__((constructor)) void init(void)
 {
   LTT_TRACEFILE_NAME_METADATA = g_quark_from_string("metadata");
 }
+
+/*****************************************************************************
+ *Function name
+ *    ltt_tracefile_open_header    : based on ltt_tracefile_open but it stops
+ *                                  when it gets the header
+ *Input params
+ *    fileName       : path to the tracefile
+ *    tf             : the tracefile (metadata_0) where the header will be read
+ *Return value
+ *    ltt_subbuffer_header_t         : the header containing the version number
+ ****************************************************************************/
+static ltt_subbuffer_header_t * ltt_tracefile_open_header(gchar *fileName, LttTracefile *tf)
+{
+        struct stat    lTDFStat;    /* Trace data file status */
+        ltt_subbuffer_header_t *header;
+        int page_size = getpagesize();
+
+        /* open the file */
+        tf->long_name = g_quark_from_string(fileName);
+        tf->fd = open(fileName, O_RDONLY);
+        if(tf->fd < 0){
+                g_warning("Unable to open input data file %s\n", fileName);
+                goto end;
+        }
+
+        /* Get the file's status */
+        if(fstat(tf->fd, &lTDFStat) < 0){
+                g_warning("Unable to get the status of the input data file %s\n", fileName);
+                goto close_file;
+        }
+
+        /* Is the file large enough to contain a trace */
+        if(lTDFStat.st_size < (off_t)(ltt_subbuffer_header_size())) {
+                g_print("The input data file %s does not contain a trace\n", fileName);
+                goto close_file;
+        }
+
+        /* Temporarily map the buffer start header to get trace information */
+        /* Multiple of pages aligned head */
+        tf->buffer.head = mmap(0,PAGE_ALIGN(ltt_subbuffer_header_size()), PROT_READ, MAP_PRIVATE, tf->fd, 0);
+
+        if(tf->buffer.head == MAP_FAILED) {
+                perror("Error in allocating memory for buffer of tracefile");
+                goto close_file;
+        }
+        g_assert( ( (gulong)tf->buffer.head&(8-1) ) == 0); // make sure it's aligned.
+
+        header = (ltt_subbuffer_header_t *)tf->buffer.head;
+
+        return header;
+
+        close_file:
+                close(tf->fd);
+        end:
+                return 0;
+}
+
+
+/*****************************************************************************
+ *Function name
+ *    get_version    : get the trace version from a metadata_0 trace file
+ *Input params
+ *    pathname       : path to the trace
+ *    version_number  : the struct that will get the version number
+ *Return value
+ *    int         : 1 if succeed, -1 if error
+ ****************************************************************************/
+int ltt_get_trace_version(const gchar *pathname, struct LttTraceVersion *version_number)
+{
+       gchar abs_path[PATH_MAX];
+       int ret = 0;
+       DIR *dir;
+       struct dirent *entry;
+       struct stat stat_buf;
+       gchar path[PATH_MAX];
+
+       LttTracefile tmp_tf;
+       LttTrace  * t;
+       ltt_subbuffer_header_t *header;
+
+       t = g_new(LttTrace, 1);
+
+       get_absolute_pathname(pathname, abs_path);
+
+       /* Test to see if it looks like a trace */
+       dir = opendir(abs_path);
+
+       if(dir == NULL) {
+               perror(abs_path);
+               goto open_error;
+       }
+
+       while((entry = readdir(dir)) != NULL) {
+               strcpy(path, abs_path);
+               strcat(path, "/");
+               strcat(path, entry->d_name);
+               ret = stat(path, &stat_buf);
+               if(ret == -1) {
+                       perror(path);
+                       continue;
+               }
+       }
+
+       closedir(dir);
+       dir = opendir(abs_path);
+
+       while((entry = readdir(dir)) != NULL) {
+               if(entry->d_name[0] == '.') continue;
+               if(g_strcmp0(entry->d_name, "metadata_0") != 0) continue;
+
+               strcpy(path, abs_path);
+               strcat(path, "/");
+               strcat(path, entry->d_name);
+               if(ret == -1) {
+                       perror(path);
+                       continue;
+               }
+
+                header = ltt_tracefile_open_header(path, &tmp_tf);
+
+               if(header == NULL) {
+                       g_info("Error getting the header %s", path);
+                       continue; /* error opening the tracefile : bad magic number ? */
+               }
+
+                version_number->ltt_major_version = header->major_version;
+                version_number->ltt_minor_version = header->minor_version;
+       }
+
+       return 0;
+
+       open_error:
+                g_free(t);
+                return -1;
+}
This page took 0.024907 seconds and 4 git commands to generate.