- LttTime lttTime;
- int headTime = timecmp(&(t->a_block_start->time), &time);
- int tailTime = timecmp(&(t->a_block_end->time), &time);
-
- if(headTime < 0 && tailTime > 0){
- lttTime = getEventTime(t);
- err = timecmp(<tTime, &time);
- if(err > 0){
- if(t->which_event==2 || timecmp(&t->prev_event_time,&time)<0){
- return;
- }else{
- updateTracefile(t);
- return ltt_tracefile_seek_time(t, time);
- }
- }else if(err < 0){
- err = t->which_block;
- if(ltt_tracefile_read(t) == NULL){
- g_print("End of file\n");
- return;
- }
- if(t->which_block == err)
- return ltt_tracefile_seek_time(t,time);
- }else return;
- }else if(headTime > 0){
- if(t->which_block == 1){
- updateTracefile(t);
- }else{
- if(timecmp(&(t->prev_block_end_time),&time) >= 0 ){
- err=readBlock(t,t->which_block-1);
- if(err) g_error("Can not read tracefile: %s\n", t->name);
- return ltt_tracefile_seek_time(t, time) ;
- }else{
- updateTracefile(t);
- }
- }
- }else if(tailTime < 0){
- if(t->which_block != t->block_number){
- err=readBlock(t,t->which_block+1);
- if(err) g_error("Can not read tracefile: %s\n", t->name);
- }else {
- g_print("End of file\n");
- return;
- }
- if(tailTime < 0) return ltt_tracefile_seek_time(t, time);
- }else if(headTime == 0){
- updateTracefile(t);
- }else if(tailTime == 0){
- t->cur_event_pos = t->a_block_end - EVENT_HEADER_SIZE;
- return;
+
+ 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;
+ }
+
+ } if(ltt_time_compare(time, tf->buffer.begin.timestamp) < 0) {
+ /* go to lower part */
+ high = block_num;
+ } else if(ltt_time_compare(time, tf->buffer.end.timestamp) > 0) {
+ /* go to higher part */
+ low = block_num;
+ } else {/* The event is right in the buffer!
+ (or in the next buffer first event) */
+ while(1) {
+ 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;
+ }
+ goto found;
+ }
+ }
+
+found:
+ return 0;
+
+ /* Error handling */
+fail:
+ g_error("ltt_tracefile_seek_time failed on tracefile %s",
+ g_quark_to_string(tf->name));
+ return EPERM;
+}
+
+
+int ltt_tracefile_seek_position(LttTracefile *tf, const LttEventPosition *ep) {
+
+ int err;
+
+ if(ep->tracefile != tf) {
+ goto fail;