+ if(events_request->end_position != NULL && end_position != NULL &&
+ lttv_traceset_context_pos_pos_compare(events_request->end_position,
+ end_position) <0)
+ end_position = events_request->end_position;
+ }
+ }
+
+ {
+ /* 3.3.2 Find lowest start position in list_out */
+ GSList *iter;
+
+ for(iter=list_out;iter!=NULL;iter=g_slist_next(iter)) {
+ EventsRequest *events_request = (EventsRequest*)iter->data;
+
+ if(events_request->end_position != NULL && end_position != NULL &&
+ lttv_traceset_context_pos_pos_compare(events_request->end_position,
+ end_position) <0)
+ end_position = events_request->end_position;
+ }
+ }
+
+ {
+ /* 4. Call process traceset middle */
+ g_debug("Calling process traceset middle with %p, %lu sec %lu nsec, %u nb ev, %p end pos", tsc, end_time.tv_sec, end_time.tv_nsec, end_nb_events, end_position);
+ count = lttv_process_traceset_middle(tsc, end_time, end_nb_events, end_position);
+
+ tfc = lttv_traceset_context_get_current_tfc(tsc);
+ if(tfc != NULL)
+ g_debug("Context time after middle : %lu, %lu", tfc->timestamp.tv_sec,
+ tfc->timestamp.tv_nsec);
+ else
+ g_debug("End of trace reached after middle.");
+
+ }
+ {
+ /* 5. After process traceset middle */
+ tfc = lttv_traceset_context_get_current_tfc(tsc);
+
+ /* - if current context time > traceset.end time */
+ if(tfc == NULL || ltt_time_compare(tfc->timestamp,
+ tsc->time_span.end_time) > 0) {
+ /* - For each req in list_in */
+ GSList *iter = list_in;
+
+ while(iter != NULL) {
+
+ gboolean remove = FALSE;
+ gboolean free_data = FALSE;
+ EventsRequest *events_request = (EventsRequest *)iter->data;
+
+ /* - Remove events hooks for req
+ * - Call end chunk for req
+ */
+
+ if(events_request->trace == -1)
+ lttv_process_traceset_end(tsc,
+ events_request->after_chunk_traceset,
+ events_request->after_chunk_trace,
+ events_request->after_chunk_tracefile,
+ events_request->event,
+ events_request->event_by_id);
+
+ else {
+ guint nb_trace = lttv_traceset_number(tsc->ts);
+ g_assert(events_request->trace < nb_trace &&
+ events_request->trace > -1);
+ LttvTraceContext *tc = tsc->traces[events_request->trace];
+
+ lttv_trace_context_remove_hooks(tc,
+ events_request->after_chunk_trace,
+ events_request->after_chunk_tracefile,
+ events_request->event,
+ events_request->event_by_id);
+ lttv_hooks_call(events_request->after_chunk_traceset, tsc);
+
+
+ }
+
+ /* - Call end request for req */
+ lttv_hooks_call(events_request->after_request, (gpointer)tsc);
+
+ /* - remove req from list_in */
+ /* Destroy the request */
+ remove = TRUE;
+ free_data = TRUE;
+
+ /* Go to next */
+ if(remove)
+ {
+ GSList *remove_iter = iter;
+
+ iter = g_slist_next(iter);
+ if(free_data) events_request_free((EventsRequest*)remove_iter->data);
+ list_in = g_slist_remove_link(list_in, remove_iter);
+ } else { // not remove
+ iter = g_slist_next(iter);
+ }
+ }
+ }
+ {
+ /* 5.1 For each req in list_in */
+ GSList *iter = list_in;
+
+ while(iter != NULL) {
+
+ gboolean remove = FALSE;
+ gboolean free_data = FALSE;
+ EventsRequest *events_request = (EventsRequest *)iter->data;
+
+ /* - Remove events hooks for req
+ * - Call end chunk for req
+ */
+ if(events_request->trace == -1)
+ lttv_process_traceset_end(tsc,
+ events_request->after_chunk_traceset,
+ events_request->after_chunk_trace,
+ events_request->after_chunk_tracefile,
+ events_request->event,
+ events_request->event_by_id);
+
+ else {
+ guint nb_trace = lttv_traceset_number(tsc->ts);
+ g_assert(events_request->trace < nb_trace &&
+ events_request->trace > -1);
+ LttvTraceContext *tc = tsc->traces[events_request->trace];
+
+ lttv_trace_context_remove_hooks(tc,
+ events_request->after_chunk_trace,
+ events_request->after_chunk_tracefile,
+ events_request->event,
+ events_request->event_by_id);
+
+ lttv_hooks_call(events_request->after_chunk_traceset, tsc);
+ }
+
+ /* - req.num -= count */
+ g_assert(events_request->num_events >= count);
+ events_request->num_events -= count;
+
+ g_assert(tfc != NULL);
+ /* - if req.num == 0
+ * or
+ * current context time >= req.end time
+ * or
+ * req.end pos == current pos
+ * or
+ * req.stop_flag == TRUE
+ */
+ if( events_request->num_events == 0
+ ||
+ events_request->stop_flag == TRUE
+ ||
+ ltt_time_compare(tfc->timestamp,
+ events_request->end_time) >= 0
+ ||
+ (events_request->end_position != NULL
+ &&
+ lttv_traceset_context_ctx_pos_compare(tsc,
+ events_request->end_position) == 0)
+
+ ) {
+ g_assert(events_request->servicing == TRUE);
+ /* - Call end request for req
+ * - remove req from list_in */
+ lttv_hooks_call(events_request->after_request, (gpointer)tsc);
+ /* - remove req from list_in */
+ /* Destroy the request */
+ remove = TRUE;
+ free_data = TRUE;
+ }
+
+ /* Go to next */
+ if(remove)
+ {
+ GSList *remove_iter = iter;
+
+ iter = g_slist_next(iter);
+ if(free_data) events_request_free((EventsRequest*)remove_iter->data);
+ list_in = g_slist_remove_link(list_in, remove_iter);
+ } else { // not remove
+ iter = g_slist_next(iter);
+ }
+ }
+ }
+ }
+ }
+ /* End of removed servicing loop : leave control to GTK instead. */
+ // if(gtk_events_pending()) break;
+ //}
+
+ /* B. When interrupted between chunks */
+
+ {
+ GSList *iter = list_in;
+
+ /* 1. for each request in list_in */
+ while(iter != NULL) {
+
+ gboolean remove = FALSE;
+ gboolean free_data = FALSE;
+ EventsRequest *events_request = (EventsRequest *)iter->data;
+
+ /* 1.1. Use current postition as start position */
+ if(events_request->start_position != NULL)
+ lttv_traceset_context_position_destroy(events_request->start_position);
+ events_request->start_position = lttv_traceset_context_position_new();
+ lttv_traceset_context_position_save(tsc, events_request->start_position);
+
+ /* 1.2. Remove start time */
+ events_request->start_time = ltt_time_infinite;
+
+ /* 1.3. Move from list_in to list_out */
+ remove = TRUE;
+ free_data = FALSE;
+ list_out = g_slist_append(list_out, events_request);
+
+ /* Go to next */
+ if(remove)
+ {
+ GSList *remove_iter = iter;
+
+ iter = g_slist_next(iter);
+ if(free_data) events_request_free((EventsRequest*)remove_iter->data);
+ list_in = g_slist_remove_link(list_in, remove_iter);
+ } else { // not remove
+ iter = g_slist_next(iter);
+ }
+ }
+
+
+ }
+
+ /* C Unlock Traces */
+ {
+ //lttv_process_traceset_get_sync_data(tsc);
+
+ guint iter_trace;
+
+ for(iter_trace=0;
+ iter_trace<lttv_traceset_number(tsc->ts);
+ iter_trace++) {
+ LttvTrace *trace_v = lttv_traceset_get(tsc->ts, iter_trace);
+
+ lttvwindowtraces_unlock(trace_v);
+ }
+ }
+
+#if 0
+ //set the cursor back to normal
+ gdk_window_set_cursor(win, NULL);
+#endif //0
+
+ g_assert(g_slist_length(list_in) == 0);
+
+ if( g_slist_length(list_out) == 0 ) {
+ /* Put tab's request pending flag back to normal */
+ tab->events_request_pending = FALSE;
+ g_debug("remove the idle fct");
+ return FALSE; /* Remove the idle function */
+ }
+ g_debug("leave the idle fct");
+ return TRUE; /* Leave the idle function */
+
+ /* We do not use simili-round-robin, it may require to read 1 meg buffers
+ * again and again if many tracesets use the same tracefiles. */
+ /* Hack for round-robin idle functions */
+ /* It will put the idle function at the end of the pool */
+ /*g_idle_add_full((G_PRIORITY_HIGH_IDLE + 21),
+ (GSourceFunc)execute_events_requests,
+ tab,
+ NULL);
+ return FALSE;
+ */
+}
+
+#undef list_out
+
+
+static void lttvwindow_add_trace(Tab *tab, LttvTrace *trace_v)
+{
+ LttvTraceset *traceset = tab->traceset_info->traceset;
+ guint i;
+ guint num_traces = lttv_traceset_number(traceset);
+
+ //Verify if trace is already present.
+ for(i=0; i<num_traces; i++)
+ {
+ LttvTrace * trace = lttv_traceset_get(traceset, i);
+ if(trace == trace_v)
+ return;
+ }
+
+ //Keep a reference to the traces so they are not freed.
+ for(i=0; i<lttv_traceset_number(traceset); i++)
+ {
+ LttvTrace * trace = lttv_traceset_get(traceset, i);
+ lttv_trace_ref(trace);
+ }
+
+ //remove state update hooks
+ lttv_state_remove_event_hooks(
+ (LttvTracesetState*)tab->traceset_info->traceset_context);
+
+ lttv_context_fini(LTTV_TRACESET_CONTEXT(
+ tab->traceset_info->traceset_context));
+ g_object_unref(tab->traceset_info->traceset_context);
+
+ lttv_traceset_add(traceset, trace_v);
+ lttv_trace_ref(trace_v); /* local ref */
+
+ /* Create new context */
+ tab->traceset_info->traceset_context =
+ g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
+ lttv_context_init(
+ LTTV_TRACESET_CONTEXT(tab->traceset_info->
+ traceset_context),
+ traceset);
+
+
+ //add state update hooks
+ lttv_state_add_event_hooks(
+ (LttvTracesetState*)tab->traceset_info->traceset_context);
+ //Remove local reference to the traces.
+ for(i=0; i<lttv_traceset_number(traceset); i++)
+ {
+ LttvTrace * trace = lttv_traceset_get(traceset, i);
+ lttv_trace_unref(trace);
+ }
+
+ //FIXME
+ //add_trace_into_traceset_selector(GTK_MULTIVPANED(tab->multivpaned), lttv_trace(trace_v));
+}
+
+/* add_trace adds a trace into the current traceset. It first displays a
+ * directory selection dialogue to let user choose a trace, then recreates
+ * tracset_context, and redraws all the viewer of the current tab
+ */
+
+void add_trace(GtkWidget * widget, gpointer user_data)
+{
+ LttTrace *trace;
+ LttvTrace * trace_v;
+ LttvTraceset * traceset;
+ const char * dir;
+ char abs_path[PATH_MAX];
+ gint id;
+ MainWindow * mw_data = get_window_data_struct(widget);
+ GtkWidget * notebook = lookup_widget(widget, "MNotebook");
+
+ GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
+ gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
+ Tab *tab;
+
+ if(!page) {
+ tab = create_new_tab(widget, NULL);
+ } else {
+ tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
+ }
+
+ GtkDirSelection * file_selector = (GtkDirSelection *)gtk_dir_selection_new("Select a trace");
+ gtk_dir_selection_hide_fileop_buttons(file_selector);
+
+ if(remember_trace_dir[0] != '\0')
+ gtk_dir_selection_set_filename(file_selector, remember_trace_dir);
+
+ id = gtk_dialog_run(GTK_DIALOG(file_selector));
+ switch(id){
+ case GTK_RESPONSE_ACCEPT:
+ case GTK_RESPONSE_OK:
+ dir = gtk_dir_selection_get_dir (file_selector);
+ strncpy(remember_trace_dir, dir, PATH_MAX);
+ if(!dir || strlen(dir) == 0){
+ gtk_widget_destroy((GtkWidget*)file_selector);
+ break;
+ }
+ get_absolute_pathname(dir, abs_path);
+ trace_v = lttvwindowtraces_get_trace_by_name(abs_path);
+ if(trace_v == NULL) {
+ trace = ltt_trace_open(abs_path);
+ if(trace == NULL) {
+ g_warning("cannot open trace %s", abs_path);
+ } else {
+ trace_v = lttv_trace_new(trace);
+ lttvwindowtraces_add_trace(trace_v);
+ lttvwindow_add_trace(tab, trace_v);
+ }
+ } else {
+ lttvwindow_add_trace(tab, trace_v);
+ }
+
+ gtk_widget_destroy((GtkWidget*)file_selector);
+
+ //update current tab
+ //update_traceset(mw_data);
+
+ /* Call the updatetraceset hooks */
+
+ traceset = tab->traceset_info->traceset;
+ SetTraceset(tab, traceset);
+ // in expose now call_pending_read_hooks(mw_data);
+
+ //lttvwindow_report_current_time(mw_data,&(tab->current_time));
+ break;
+ case GTK_RESPONSE_REJECT:
+ case GTK_RESPONSE_CANCEL:
+ default:
+ gtk_widget_destroy((GtkWidget*)file_selector);
+ break;
+ }
+}
+
+/* remove_trace removes a trace from the current traceset if all viewers in
+ * the current tab are not interested in the trace. It first displays a
+ * dialogue, which shows all traces in the current traceset, to let user choose
+ * a trace, then it checks if all viewers unselect the trace, if it is true,