+
+ /* Find process pid_in in the list... */
+ process = tfs->process;
+ /* It should exist, because we are after the state update. */
+ g_assert(process != NULL);
+
+ guint pid = process->pid;
+
+ birth = process->creation_time;
+ const gchar *name = g_quark_to_string(process->name);
+
+ if(processlist_get_process_pixels(process_list,
+ pid,
+ process->last_cpu,
+ &birth,
+ tfc->t_context->index,
+ &y,
+ &height,
+ &hashed_process_data) == 1)
+ {
+ g_assert(pid == 0 || pid != process->ppid);
+ /* Process not present */
+ processlist_add(process_list,
+ pid,
+ process->last_cpu,
+ process->ppid,
+ &birth,
+ tfc->t_context->index,
+ name,
+ &pl_height,
+ &hashed_process_data);
+ processlist_get_process_pixels(process_list,
+ pid,
+ process->last_cpu,
+ &birth,
+ tfc->t_context->index,
+ &y,
+ &height,
+ &hashed_process_data);
+ drawing_insert_square( control_flow_data->drawing, y, height);
+ }
+
+ convert_time_to_pixels(
+ time_window.start_time,
+ end_time,
+ evtime,
+ width,
+ &hashed_process_data->x.over);
+ return 0;
+}
+
+
+
+/* before_process_hook
+ *
+ * Draw lines for process event.
+ *
+ * @param hook_data ControlFlowData structure of the viewer.
+ * @param call_data Event context.
+ *
+ * This function adds items to be drawn in a queue for each process.
+ *
+ */
+int before_process_hook(void *hook_data, void *call_data)
+{
+ EventsRequest *events_request = (EventsRequest*)hook_data;
+ ControlFlowData *control_flow_data = events_request->viewer_data;
+ Drawing_t *drawing = control_flow_data->drawing;
+
+ LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
+
+ LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+ LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
+
+ LttEvent *e;
+ e = tfc->e;
+
+ LttTime evtime = ltt_event_time(e);
+ TimeWindow time_window =
+ lttvwindow_get_time_window(control_flow_data->tab);
+
+ LttTime end_time = ltt_time_add(time_window.start_time,
+ time_window.time_width);
+
+ if(ltt_time_compare(evtime, time_window.start_time) == -1
+ || ltt_time_compare(evtime, end_time) == 1)
+ return;
+
+ guint width = control_flow_data->drawing->width;
+
+ guint sub_id;
+ {
+ LttField *f = ltt_event_field(e);
+ LttField *element;
+ element = ltt_field_member(f,0);
+ sub_id = ltt_event_get_long_unsigned(e,element);
+ }
+
+ if(sub_id == 3) { /* exit */
+
+ /* Add process to process list (if not present) */
+ LttvProcessState *process = tfs->process;
+ guint pid = process->pid;
+ LttTime birth;
+ guint y = 0, height = 0, pl_height = 0;
+ HashedProcessData *hashed_process_data = NULL;
+
+ ProcessList *process_list =
+ guicontrolflow_get_process_list(control_flow_data);
+
+ g_assert(process != NULL);
+
+ birth = process->creation_time;
+ const gchar *name = g_quark_to_string(process->name);
+
+ if(processlist_get_process_pixels(process_list,
+ pid,
+ process->last_cpu,
+ &birth,
+ tfc->t_context->index,
+ &y,
+ &height,
+ &hashed_process_data) == 1)
+ {
+ g_assert(pid == 0 || pid != process->ppid);
+ /* Process not present */
+ processlist_add(process_list,
+ pid,
+ process->last_cpu,
+ process->ppid,
+ &birth,
+ tfc->t_context->index,
+ name,
+ &pl_height,
+ &hashed_process_data);
+ processlist_get_process_pixels(process_list,
+ pid,
+ process->last_cpu,
+ &birth,
+ tfc->t_context->index,
+ &y,
+ &height,
+ &hashed_process_data);
+ drawing_insert_square( control_flow_data->drawing, y, height);
+ }
+
+ /* Now, the process is in the state hash and our own process hash.
+ * We definitely can draw the items related to the ending state.
+ */
+
+ /* Check if the x position is unset. In can have been left unset by
+ * a draw closure from a after chunk hook. This should never happen,
+ * because it must be set by before chunk hook to the damage_begin
+ * value.
+ */
+ g_assert(hashed_process_data->x.over != -1);
+ {
+ guint x;
+
+ convert_time_to_pixels(
+ time_window.start_time,
+ end_time,
+ evtime,
+ width,
+ &x);
+
+
+ /* Jump over draw if we are at the same x position */
+ if(x == hashed_process_data->x.middle)
+ {
+ /* jump */
+ } else {
+ DrawContext draw_context;
+
+ /* Now create the drawing context that will be used to draw
+ * items related to the last state. */
+ draw_context.drawable = drawing->pixmap;
+ draw_context.gc = drawing->gc;
+ draw_context.pango_layout = drawing->pango_layout;
+ draw_context.drawinfo.start.x = hashed_process_data->x.middle;
+ draw_context.drawinfo.end.x = x;
+
+ draw_context.drawinfo.y.over = y+1;
+ draw_context.drawinfo.y.middle = y+(height/2);
+ draw_context.drawinfo.y.under = y+height;
+
+ draw_context.drawinfo.start.offset.over = 0;
+ draw_context.drawinfo.start.offset.middle = 0;
+ draw_context.drawinfo.start.offset.under = 0;
+ draw_context.drawinfo.end.offset.over = 0;
+ draw_context.drawinfo.end.offset.middle = 0;
+ draw_context.drawinfo.end.offset.under = 0;
+
+ {
+ /* Draw the line */
+ PropertiesLine prop_line = prepare_status_line(process);
+ draw_line((void*)&prop_line, (void*)&draw_context);
+
+ }
+ /* become the last x position */
+ hashed_process_data->x.middle = x;
+ }
+ }
+
+ }
+ return 0;
+
+}
+
+
+
+
+
+
+/* after_process_hook
+ *
+ * Create the processlist entry for the child process. Put the last
+ * position in x at the current time value.
+ *
+ * @param hook_data ControlFlowData structure of the viewer.
+ * @param call_data Event context.
+ *
+ * This function adds items to be drawn in a queue for each process.
+ *
+ */
+int after_process_hook(void *hook_data, void *call_data)
+{
+ EventsRequest *events_request = (EventsRequest*)hook_data;
+ ControlFlowData *control_flow_data = events_request->viewer_data;
+
+ LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
+
+ LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+ LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
+
+ LttEvent *e;
+ e = tfc->e;
+
+ LttTime evtime = ltt_event_time(e);
+ TimeWindow time_window =
+ lttvwindow_get_time_window(control_flow_data->tab);
+
+ LttTime end_time = ltt_time_add(time_window.start_time,
+ time_window.time_width);
+
+ if(ltt_time_compare(evtime, time_window.start_time) == -1
+ || ltt_time_compare(evtime, end_time) == 1)
+ return;
+
+ guint width = control_flow_data->drawing->width;
+
+ guint sub_id;
+ guint param1;
+ {
+ LttField *f = ltt_event_field(e);
+ LttField *element;
+ element = ltt_field_member(f,0);
+ sub_id = ltt_event_get_long_unsigned(e,element);
+ element = ltt_field_member(f,1);
+ param1 = ltt_event_get_long_unsigned(e,element);
+ }
+
+ if(sub_id == 2) { /* fork */
+
+ guint child_pid = param1;
+ /* Add process to process list (if not present) */
+ LttvProcessState *process_child;
+ LttTime birth;
+ guint y_child = 0, height = 0, pl_height = 0;
+ HashedProcessData *hashed_process_data_child = NULL;
+
+ ProcessList *process_list =
+ guicontrolflow_get_process_list(control_flow_data);
+
+
+ /* Find child in the list... */
+ process_child = lttv_state_find_process(tfs, child_pid);
+ /* It should exist, because we are after the state update. */
+ g_assert(process_child != NULL);
+
+ birth = process_child->creation_time;
+ const gchar *name = g_quark_to_string(process_child->name);
+
+ if(processlist_get_process_pixels(process_list,
+ child_pid,
+ process_child->last_cpu,
+ &birth,
+ tfc->t_context->index,
+ &y_child,
+ &height,
+ &hashed_process_data_child) == 1)
+ {
+ g_assert(child_pid == 0 || child_pid != process_child->ppid);
+ /* Process not present */
+ processlist_add(process_list,
+ child_pid,
+ process_child->last_cpu,
+ process_child->ppid,
+ &birth,
+ tfc->t_context->index,
+ name,
+ &pl_height,
+ &hashed_process_data_child);
+ processlist_get_process_pixels(process_list,
+ child_pid,
+ process_child->last_cpu,
+ &birth,
+ tfc->t_context->index,
+ &y_child,
+ &height,
+ &hashed_process_data_child);
+ drawing_insert_square( control_flow_data->drawing, y_child, height);
+ }
+
+ guint new_x;
+ convert_time_to_pixels(
+ time_window.start_time,
+ end_time,
+ evtime,
+ width,
+ &new_x);
+ hashed_process_data_child->x.over = new_x;
+ hashed_process_data_child->x.middle = new_x;
+ hashed_process_data_child->x.under = new_x;
+
+ } else if(sub_id == 3) { /* exit */
+
+ /* Add process to process list (if not present) */
+ LttvProcessState *process = tfs->process;
+ guint pid = process->pid;
+ LttTime birth;
+ guint y = 0, height = 0, pl_height = 0;
+ HashedProcessData *hashed_process_data = NULL;
+
+ ProcessList *process_list =
+ guicontrolflow_get_process_list(control_flow_data);
+
+
+ /* It should exist, because we are after the state update. */
+ g_assert(process != NULL);
+
+ birth = process->creation_time;
+ const gchar *name = g_quark_to_string(process->name);
+
+ if(processlist_get_process_pixels(process_list,
+ pid,
+ process->last_cpu,
+ &birth,
+ tfc->t_context->index,
+ &y,
+ &height,
+ &hashed_process_data) == 1)
+ {
+ g_assert(pid == 0 || pid != process->ppid);
+ /* Process not present */
+ processlist_add(process_list,
+ pid,
+ process->last_cpu,
+ process->ppid,
+ &birth,
+ tfc->t_context->index,
+ name,
+ &pl_height,
+ &hashed_process_data);
+ processlist_get_process_pixels(process_list,
+ pid,
+ process->last_cpu,
+ &birth,
+ tfc->t_context->index,
+ &y,
+ &height,
+ &hashed_process_data);
+ drawing_insert_square( control_flow_data->drawing, y, height);
+ }
+
+ guint new_x;
+ convert_time_to_pixels(
+ time_window.start_time,
+ end_time,
+ evtime,
+ width,
+ &new_x);
+ hashed_process_data->x.middle = new_x;
+ }
+ return 0;
+
+}
+
+
+gint update_time_window_hook(void *hook_data, void *call_data)
+{
+ ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
+ Drawing_t *drawing = control_flow_data->drawing;
+
+ const TimeWindowNotifyData *time_window_nofify_data =
+ ((const TimeWindowNotifyData *)call_data);
+
+ TimeWindow *old_time_window =
+ time_window_nofify_data->old_time_window;
+ TimeWindow *new_time_window =
+ time_window_nofify_data->new_time_window;
+
+ /* Update the ruler */
+ drawing_update_ruler(control_flow_data->drawing,
+ new_time_window);
+
+
+ /* Two cases : zoom in/out or scrolling */
+
+ /* In order to make sure we can reuse the old drawing, the scale must
+ * be the same and the new time interval being partly located in the
+ * currently shown time interval. (reuse is only for scrolling)
+ */
+
+ g_info("Old time window HOOK : %u, %u to %u, %u",
+ old_time_window->start_time.tv_sec,
+ old_time_window->start_time.tv_nsec,
+ old_time_window->time_width.tv_sec,
+ old_time_window->time_width.tv_nsec);
+
+ g_info("New time window HOOK : %u, %u to %u, %u",
+ new_time_window->start_time.tv_sec,
+ new_time_window->start_time.tv_nsec,
+ new_time_window->time_width.tv_sec,
+ new_time_window->time_width.tv_nsec);
+
+ if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
+ && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
+ {
+ /* Same scale (scrolling) */
+ g_info("scrolling");
+ LttTime *ns = &new_time_window->start_time;
+ LttTime *os = &old_time_window->start_time;
+ LttTime old_end = ltt_time_add(old_time_window->start_time,
+ old_time_window->time_width);
+ LttTime new_end = ltt_time_add(new_time_window->start_time,
+ new_time_window->time_width);
+ //if(ns<os+w<ns+w)
+ //if(ns<os+w && os+w<ns+w)
+ //if(ns<old_end && os<ns)
+ if(ltt_time_compare(*ns, old_end) == -1
+ && ltt_time_compare(*os, *ns) == -1)
+ {
+ g_info("scrolling near right");
+ /* Scroll right, keep right part of the screen */
+ guint x = 0;
+ guint width = control_flow_data->drawing->width;
+ convert_time_to_pixels(
+ *os,
+ old_end,
+ *ns,
+ width,
+ &x);
+
+ /* Copy old data to new location */
+ gdk_draw_drawable (control_flow_data->drawing->pixmap,
+ control_flow_data->drawing->drawing_area->style->black_gc,
+ control_flow_data->drawing->pixmap,
+ x, 0,
+ 0, 0,
+ control_flow_data->drawing->width-x+SAFETY, -1);
+
+ if(drawing->damage_begin == drawing->damage_end)
+ drawing->damage_begin = control_flow_data->drawing->width-x;
+ else
+ drawing->damage_begin = 0;
+
+ drawing->damage_end = control_flow_data->drawing->width;
+
+ /* Clear the data request background, but not SAFETY */
+ gdk_draw_rectangle (control_flow_data->drawing->pixmap,
+ //control_flow_data->drawing->drawing_area->style->black_gc,
+ control_flow_data->drawing->drawing_area->style->black_gc,
+ TRUE,
+ drawing->damage_begin+SAFETY, 0,
+ drawing->damage_end - drawing->damage_begin, // do not overlap
+ control_flow_data->drawing->height);
+
+ gtk_widget_queue_draw_area (drawing->drawing_area,
+ 0,0,
+ control_flow_data->drawing->width,
+ control_flow_data->drawing->height);
+
+ /* Get new data for the rest. */
+ drawing_data_request(control_flow_data->drawing,
+ &control_flow_data->drawing->pixmap,
+ drawing->damage_begin, 0,
+ drawing->damage_end - drawing->damage_begin,
+ control_flow_data->drawing->height);
+ } else {
+ //if(ns<os<ns+w)
+ //if(ns<os && os<ns+w)
+ //if(ns<os && os<new_end)
+ if(ltt_time_compare(*ns,*os) == -1
+ && ltt_time_compare(*os,new_end) == -1)
+ {
+ g_info("scrolling near left");
+ /* Scroll left, keep left part of the screen */
+ guint x = 0;
+ guint width = control_flow_data->drawing->width;
+ convert_time_to_pixels(
+ *ns,
+ new_end,
+ *os,
+ width,
+ &x);
+
+