+
+ err = map_block(tf, 0);
+ if(unlikely(err)) {
+ g_error("Can not map block");
+ *start = ltt_time_infinite;
+ } else
+ *start = tf->buffer.begin.timestamp;
+
+ err = map_block(tf, tf->num_blocks - 1); /* Last block */
+ if(unlikely(err)) {
+ g_error("Can not map block");
+ *end = ltt_time_zero;
+ } else
+ *end = tf->buffer.end.timestamp;
+}
+
+struct tracefile_time_span_get_args {
+ LttTrace *t;
+ LttTime *start;
+ LttTime *end;
+};
+
+static void group_time_span_get(GQuark name, gpointer data, gpointer user_data)
+{
+ struct tracefile_time_span_get_args *args =
+ (struct tracefile_time_span_get_args*)user_data;
+
+ GArray *group = (GArray *)data;
+ int i;
+ LttTracefile *tf;
+ LttTime tmp_start;
+ LttTime tmp_end;
+
+ for(i=0; i<group->len; i++) {
+ tf = &g_array_index (group, LttTracefile, i);
+ if(tf->cpu_online) {
+ ltt_tracefile_time_span_get(tf, &tmp_start, &tmp_end);
+ if(ltt_time_compare(*args->start, tmp_start)>0) *args->start = tmp_start;
+ if(ltt_time_compare(*args->end, tmp_end)<0) *args->end = tmp_end;
+ }
+ }
+}
+
+void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end)
+{
+ LttTime min_start = ltt_time_infinite;
+ LttTime max_end = ltt_time_zero;
+ struct tracefile_time_span_get_args args = { t, &min_start, &max_end };
+
+ g_datalist_foreach(&t->tracefiles, &group_time_span_get, &args);
+
+ if(start != NULL) *start = min_start;
+ if(end != NULL) *end = max_end;
+
+}
+
+
+/*****************************************************************************
+ *Get the name of a tracefile
+ ****************************************************************************/
+
+GQuark ltt_tracefile_name(LttTracefile *tf)
+{
+ return tf->name;
+}
+
+/*****************************************************************************
+ * Get the number of blocks in the tracefile
+ ****************************************************************************/
+
+guint ltt_tracefile_block_number(LttTracefile *tf)
+{
+ return tf->num_blocks;
+}
+
+
+/* Seek to the first event in a tracefile that has a time equal or greater than
+ * the time passed in parameter.
+ *
+ * If the time parameter is outside the tracefile time span, seek to the first
+ * or the last event of the tracefile.
+ *
+ * If the time parameter is before the first event, we have to seek specially to
+ * there.
+ *
+ * If the time is after the end of the trace, get the last event.
+ *
+ * Do a binary search to find the right block, then a sequential search in the
+ * block to find the event.
+ *
+ * In the special case where the time requested fits inside a block that has no
+ * event corresponding to the requested time, the first event of the next block
+ * will be seeked.
+ *
+ * IMPORTANT NOTE : // FIXME everywhere...
+ *
+ * You MUST NOT do a ltt_tracefile_read right after a ltt_tracefile_seek_time :
+ * you will jump over an event if you do.
+ *
+ * Return value : 0 : no error, the tf->event can be used
+ * otherwise : this is an error.
+ *
+ * */
+
+int ltt_tracefile_seek_time(LttTracefile *tf, LttTime time)
+{
+ int ret = 0;
+ int err;
+ unsigned int block_num, high, low;
+
+ /* seek at the beginning of trace */
+ err = map_block(tf, 0); /* First block */
+ if(unlikely(err)) {
+ g_error("Can not map block");
+ goto fail;
+ }
+
+ /* If the time is lower or equal the beginning of the trace,
+ * go to the first event. */
+ if(ltt_time_compare(time, tf->buffer.begin.timestamp) <= 0) {
+ ret = ltt_tracefile_read(tf);
+ goto found; /* There is either no event in the trace or the event points
+ to the first event in the trace */
+ }
+
+ err = map_block(tf, tf->num_blocks - 1); /* Last block */
+ if(unlikely(err)) {
+ g_error("Can not map block");
+ goto fail;
+ }
+
+ /* If the time is after the end of the trace, get the last event. */
+ if(ltt_time_compare(time, tf->buffer.end.timestamp) >= 0) {
+ /* While the ltt_tracefile_read doesn't return ERANGE or EPERM,
+ * continue reading.
+ */
+ while(1) {
+ ret = ltt_tracefile_read(tf);
+ if(ret == ERANGE) goto found; /* ERANGE or EPERM */
+ else if(ret) goto fail;
+ }
+ }
+
+ /* Binary search the block */
+ high = tf->num_blocks - 1;
+ low = 0;
+
+ while(1) {
+ block_num = ((high-low) / 2) + low;
+
+ err = map_block(tf, block_num);
+ if(unlikely(err)) {
+ g_error("Can not map block");
+ goto fail;
+ }
+ if(high == low) {
+ /* We cannot divide anymore : this is what would happen if the time
+ * requested was exactly between two consecutive buffers'end and start
+ * timestamps. This is also what would happend if we didn't deal with out
+ * of span cases prior in this function. */
+ /* The event is right in the buffer!
+ * (or in the next buffer first event) */
+ while(1) {
+ ret = ltt_tracefile_read(tf);
+ if(ret == ERANGE) goto found; /* ERANGE or EPERM */
+ else if(ret) goto fail;
+
+ if(ltt_time_compare(time, tf->event.event_time) >= 0)
+ break;