Support variable sized subbuffers
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Tue, 17 Nov 2009 19:24:42 +0000 (14:24 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Tue, 17 Nov 2009 19:24:42 +0000 (14:24 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
ltt/jni_interface.c
ltt/ltt-private.h
ltt/tracefile.c

index d61f39a00747157c6b850881f80f0b0fdcac1def..ee7122f812b69730b09dd2a885dcc2980450aaee 100644 (file)
@@ -435,11 +435,11 @@ JNIEXPORT jlong JNICALL Java_org_eclipse_linuxtools_lttng_jni_JniTracefile_ltt_1
         return CONVERT_PTR_TO_JLONG(&newPtr->buffer);
 }
 
-// Get of buf_size
+// Get of buffer size
 JNIEXPORT jlong JNICALL Java_org_eclipse_linuxtools_lttng_jni_JniTracefile_ltt_1getBufferSize(JNIEnv* env, jobject jobj, jlong tracefile_ptr) {
         LttTracefile* newPtr = (LttTracefile*)CONVERT_JLONG_TO_PTR(tracefile_ptr);
         
-        return (jlong)newPtr->buf_size;
+        return (jlong)newPtr->buffer.size;
 }
 
 
index c632027710b79dc00c196c68239fc54588ee375e..23e94cc5e3de48df4b7b38445293fbc99aeb10d0 100644 (file)
@@ -66,7 +66,7 @@ typedef guint32 uint32_t;
 typedef guint64 uint64_t;
 
 /* Subbuffer header */
-struct ltt_subbuffer_header_2_4 {
+struct ltt_subbuffer_header_2_5 {
        uint64_t cycle_count_begin;     /* Cycle count at subbuffer start */
        uint64_t cycle_count_end;       /* Cycle count at subbuffer end */
        uint32_t magic_number;          /*
@@ -84,8 +84,8 @@ struct ltt_subbuffer_header_2_4 {
                                         * used all along the trace.
                                         */
        uint32_t freq_scale;            /* Frequency scaling (divide freq) */
-       uint32_t lost_size;             /* Size unused at end of subbuffer */
-       uint32_t buf_size;              /* Size of this subbuffer */
+       uint32_t data_size;             /* Size of data in subbuffer */
+       uint32_t sb_size;               /* Subbuffer size (page aligned) */
        uint32_t events_lost;           /*
                                         * Events lost in this subbuffer since
                                         * the beginning of the trace.
@@ -99,7 +99,7 @@ struct ltt_subbuffer_header_2_4 {
        char header_end[0];             /* End of header */
 };
 
-typedef struct ltt_subbuffer_header_2_4 ltt_subbuffer_header_t;
+typedef struct ltt_subbuffer_header_2_5 ltt_subbuffer_header_t;
 
 /*
  * Return header size without padding after the structure. Don't use packed
@@ -115,7 +115,10 @@ enum field_status { FIELD_UNKNOWN, FIELD_VARIABLE, FIELD_FIXED };
 
 typedef struct _LttBuffer {
   void * head;
+  guint64 offset;                /* Offset of the current subbuffer */
+  guint32 size;                  /* The size of the current subbuffer */
   unsigned int index;
+  uint32_t data_size;            /* Size of data in the subbuffer */
 
   struct {
     LttTime                 timestamp;
@@ -127,7 +130,6 @@ typedef struct _LttBuffer {
     uint64_t                cycle_count;
     uint64_t                freq; /* Frequency in khz */
   } end;
-  uint32_t                lost_size; /* Size unused at the end of the buffer */
 
   /* Timekeeping */
   uint64_t                tsc;       /* Current timestamp counter */
@@ -162,12 +164,13 @@ struct LttTracefile {
   uint32_t  events_lost;
   uint32_t  subbuf_corrupt;
 
+  GArray *buf_index;                 /* index mapping buffer index to offset */
+
   /* Current event */
   LttEvent event;                    //Event currently accessible in the trace
 
   /* Current block */
   LttBuffer buffer;                  //current buffer
-  guint32 buf_size;                  /* The size of blocks */
 };
 
 /* The characteristics of the system on which the trace was obtained
index cbb39d0e88cf1c38f9016833734f4f91f309e842..cb8cf93982a92dd7ca41fc026b9501d35ad555ae 100644 (file)
@@ -51,6 +51,8 @@
 #include <ltt/ltt-types.h>
 #include <ltt/marker.h>
 
+#define DEFAULT_N_BLOCKS 32
+
 /* from marker.c */
 extern long marker_update_fields_offsets(struct marker_info *info, const char *data);
 
@@ -148,9 +150,9 @@ static int parse_trace_header(ltt_subbuffer_header_t *header,
     break;
   case 2:
     switch(header->minor_version) {
-    case 4:
+    case 5:
       {
-        struct ltt_subbuffer_header_2_4 *vheader = header;
+        struct ltt_subbuffer_header_2_5 *vheader = header;
         tf->buffer_header_size = ltt_subbuffer_header_size();
         tf->tscbits = 27;
         tf->eventbits = 5;
@@ -198,7 +200,67 @@ static int parse_trace_header(ltt_subbuffer_header_t *header,
   return 0;
 }
 
+int get_block_offset_size(LttTracefile *tf, guint block_num,
+                          uint64_t *offset, uint32_t *size)
+{
+  uint64_t offa, offb;
+
+  if (unlikely(block_num >= tf->num_blocks))
+    return -1;
 
+  offa = g_array_index(tf->buf_index, uint64_t, block_num);
+  if (likely(block_num < tf->num_blocks - 1))
+    offb = g_array_index(tf->buf_index, uint64_t, block_num + 1);
+  else
+    offb = tf->file_size;
+  *offset = offa;
+  *size = offb - offa;
+  return 0;
+}
+
+int ltt_trace_create_block_index(LttTracefile *tf)
+{
+  int page_size = getpagesize();
+  uint64_t offset = 0;
+  unsigned long i = 0;
+  unsigned int header_map_size = PAGE_ALIGN(ltt_subbuffer_header_size());
+
+  tf->buf_index = g_array_sized_new(FALSE, TRUE, sizeof(uint64_t),
+                                    DEFAULT_N_BLOCKS);
+
+  g_assert(tf->buf_index->len == i);
+
+  while (offset < tf->file_size) {
+    ltt_subbuffer_header_t *header;
+    uint64_t *off;
+
+    tf->buf_index = g_array_set_size(tf->buf_index, i + 1);
+    off = &g_array_index(tf->buf_index, uint64_t, i);
+    *off = offset;
+
+    /* map block header */
+    header = mmap(0, header_map_size, PROT_READ, 
+                  MAP_PRIVATE, tf->fd, 0);
+    if(header == MAP_FAILED) {
+      perror("Error in allocating memory for buffer of tracefile");
+      return -1;
+    }
+
+    /* read len, offset += len */
+    offset += ltt_get_uint32(LTT_GET_BO(tf), &header->sb_size);
+
+    /* unmap block header */
+    if(munmap(header, header_map_size)) {
+      g_warning("unmap size : %u\n", header_map_size);
+      perror("munmap error");
+      return -1;
+    }
+    ++i;
+  }
+  tf->num_blocks = i;
+
+  return 0;
+}
 
 /*****************************************************************************
  *Function name
@@ -221,6 +283,7 @@ static gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf)
   tf->long_name = g_quark_from_string(fileName);
   tf->trace = t;
   tf->fd = open(fileName, O_RDONLY);
+  tf->buf_index = NULL;
   if(tf->fd < 0){
     g_warning("Unable to open input data file %s\n", fileName);
     goto end;
@@ -259,8 +322,6 @@ static gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf)
     
   //store the size of the file
   tf->file_size = lTDFStat.st_size;
-  tf->buf_size = ltt_get_uint32(LTT_GET_BO(tf), &header->buf_size);
-  tf->num_blocks = tf->file_size / tf->buf_size;
   tf->events_lost = 0;
   tf->subbuf_corrupt = 0;
 
@@ -273,6 +334,9 @@ static gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf)
   }
   tf->buffer.head = NULL;
 
+  /* Create block index */
+  ltt_trace_create_block_index(tf);
+
   //read the first block
   if(map_block(tf,0)) {
     perror("Cannot map block for tracefile");
@@ -293,6 +357,8 @@ unmap_file:
 close_file:
   close(tf->fd);
 end:
+  if (tf->buf_index)
+    g_array_free(tf->buf_index, TRUE);
   return -1;
 }
 
@@ -309,14 +375,16 @@ static void ltt_tracefile_close(LttTracefile *t)
   int page_size = getpagesize();
 
   if(t->buffer.head != NULL)
-    if(munmap(t->buffer.head, PAGE_ALIGN(t->buf_size))) {
+    if(munmap(t->buffer.head, PAGE_ALIGN(t->buffer.size))) {
     g_warning("unmap size : %u\n",
-        PAGE_ALIGN(t->buf_size));
+        PAGE_ALIGN(t->buffer.size));
     perror("munmap error");
     g_assert(0);
   }
 
   close(t->fd);
+  if (t->buf_index)
+    g_array_free(t->buf_index, TRUE);
 }
 
 /****************************************************************************
@@ -1226,8 +1294,8 @@ static void print_debug_event_header(LttEvent *ev, void *start_pos, void *end_po
 
   g_printf("Event header (tracefile %s offset %" PRIx64 "):\n",
     g_quark_to_string(ev->tracefile->long_name),
-          ((uint64_t)ev->tracefile->buffer.index * ev->tracefile->buf_size)
-          (long)start_pos - (long)ev->tracefile->buffer.head);
+          (uint64_t)ev->tracefile->buffer.offset +
+          (long)start_pos - (long)ev->tracefile->buffer.head);
 
   while (offset < (long)end_pos - (long)start_pos) {
     g_printf("%8lx", (long)start_pos - (long)ev->tracefile->buffer.head + offset);
@@ -1355,23 +1423,27 @@ static gint map_block(LttTracefile * tf, guint block_num)
 {
   int page_size = getpagesize();
   ltt_subbuffer_header_t *header;
+  uint64_t offset;
+  uint32_t size;
+  int ret;
 
   g_assert(block_num < tf->num_blocks);
 
   if(tf->buffer.head != NULL) {
-    if(munmap(tf->buffer.head, PAGE_ALIGN(tf->buf_size))) {
+    if(munmap(tf->buffer.head, PAGE_ALIGN(tf->buffer.size))) {
     g_warning("unmap size : %u\n",
-        PAGE_ALIGN(tf->buf_size));
+        PAGE_ALIGN(tf->buffer.size));
       perror("munmap error");
       g_assert(0);
     }
   }
-  
+
+  ret = get_block_offset_size(tf, block_num, &offset, &size);
+  g_assert(!ret);
+
   /* Multiple of pages aligned head */
-  tf->buffer.head = mmap(0,
-      PAGE_ALIGN(tf->buf_size),
-      PROT_READ, MAP_PRIVATE, tf->fd,
-      PAGE_ALIGN((off_t)tf->buf_size * (off_t)block_num));
+  tf->buffer.head = mmap(0, (size_t)size, PROT_READ, MAP_PRIVATE,
+                         tf->fd, (off_t)offset);
 
   if(tf->buffer.head == MAP_FAILED) {
     perror("Error in allocating memory for buffer of tracefile");
@@ -1379,7 +1451,6 @@ static gint map_block(LttTracefile * tf, guint block_num)
     goto map_error;
   }
   g_assert( ( (gulong)tf->buffer.head&(8-1) ) == 0); // make sure it's aligned.
-  
 
   tf->buffer.index = block_num;
 
@@ -1389,12 +1460,18 @@ static gint map_block(LttTracefile * tf, guint block_num)
                                               &header->cycle_count_begin);
   tf->buffer.end.cycle_count = ltt_get_uint64(LTT_GET_BO(tf),
                                               &header->cycle_count_end);
-  tf->buffer.lost_size = ltt_get_uint32(LTT_GET_BO(tf),
-                                        &header->lost_size);
+  tf->buffer.offset = offset;
+  tf->buffer.size = ltt_get_uint32(LTT_GET_BO(tf),
+                                   &header->sb_size);
+  g_assert(size == tf->buffer.size);
+  tf->buffer.data_size = ltt_get_uint32(LTT_GET_BO(tf),
+                                        &header->data_size);
   tf->buffer.tsc =  tf->buffer.begin.cycle_count;
   tf->event.tsc = tf->buffer.tsc;
   tf->buffer.freq = tf->buffer.begin.freq;
 
+  g_assert(tf->buffer.data_size <= tf->buffer.size);
+
   if (tf->trace->start_freq)
   {
     tf->buffer.begin.freq = tf->trace->start_freq;
@@ -1405,12 +1482,6 @@ static gint map_block(LttTracefile * tf, guint block_num)
       tf->buffer.end.cycle_count);
   }
 
-  /* FIXME
-   * eventually support variable buffer size : will need a partial pre-read of
-   * the headers to create an index when we open the trace... eventually. */
-  g_assert(tf->buf_size  == ltt_get_uint32(LTT_GET_BO(tf), 
-                                             &header->buf_size));
-  
   /* Make the current event point to the beginning of the buffer :
    * it means that the event read must get the first event. */
   tf->event.tracefile = tf;
@@ -1448,7 +1519,7 @@ static void print_debug_event_data(LttEvent *ev)
 
   g_printf("Event data (tracefile %s offset %" PRIx64 "):\n",
           g_quark_to_string(ev->tracefile->long_name),
-          ((uint64_t)ev->tracefile->buffer.index * ev->tracefile->buf_size)
+          (uint64_t)ev->tracefile->buffer.offset
           + (long)ev->data - (long)ev->tracefile->buffer.head);
 
   while (offset < max(ev->event_size, ev->data_size)) {
@@ -1581,7 +1652,7 @@ static int ltt_seek_next_event(LttTracefile *tf)
   if(tf->event.offset == 0) {
     tf->event.offset += tf->buffer_header_size;
 
-    if(tf->event.offset == tf->buf_size - tf->buffer.lost_size) {
+    if(tf->event.offset == tf->buffer.data_size) {
       ret = ERANGE;
     }
     goto found;
@@ -1595,11 +1666,11 @@ static int ltt_seek_next_event(LttTracefile *tf)
   
   tf->event.offset = pos - tf->buffer.head;
   
-  if(tf->event.offset == tf->buf_size - tf->buffer.lost_size) {
+  if(tf->event.offset == tf->buffer.data_size) {
     ret = ERANGE;
     goto found;
   }
-  g_assert(tf->event.offset < tf->buf_size - tf->buffer.lost_size);
+  g_assert(tf->event.offset < tf->buffer.data_size);
 
 found:
   return ret;
This page took 0.032987 seconds and 4 git commands to generate.