1 /* This file is part of the Linux Trace Toolkit Graphic User Interface
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 /* This file is the API used to launch any background computation on a trace */
21 /* Here is the implementation of the API */
23 #include <sys/types.h>
28 #include <ltt/trace.h>
30 #include <lttv/lttv.h>
31 #include <lttv/traceset.h>
32 #include <lttv/attribute.h>
33 #include <lttv/tracecontext.h>
34 #include <lttvwindow/lttvwindowtraces.h>
35 #include <lttvwindow/lttvwindow.h> // for CHUNK_NUM_EVENTS
38 typedef struct _BackgroundRequest
{
39 LttvAttributeName module_name
; /* Hook path in global attributes,
40 where all standard hooks under computation/.
42 LttvTrace
*trace
; /* trace concerned */
45 typedef struct _BackgroundNotify
{
47 LttvTrace
*trace
; /* trace */
49 LttvTracesetContextPosition
*notify_position
;
50 LttvHooks
*notify
; /* Hook to call when the notify is
51 passed, or at the end of trace */
57 gboolean
lttvwindowtraces_process_pending_requests(LttvTrace
*trace
);
59 /* Get a trace by its path name.
61 * @param path path of the trace on the virtual file system.
62 * @return Pointer to trace if found
63 * NULL is returned if the trace is not present
66 LttvTrace
*lttvwindowtraces_get_trace_by_name(gchar
*path
)
68 LttvAttribute
*attribute
= lttv_global_attributes();
71 for(i
=0;i
<lttvwindowtraces_get_number();i
++) {
72 LttvTrace
*trace_v
= lttvwindowtraces_get_trace(i
);
75 g_assert(trace_v
!= NULL
);
77 trace
= lttv_trace(trace_v
);
78 g_assert(trace
!= NULL
);
79 name
= ltt_trace_name(trace
);
81 if(strcmp(name
, path
) == 0) {
90 /* Get a trace by its number identifier */
92 LttvTrace
*lttvwindowtraces_get_trace(guint num
)
94 LttvAttribute
*g_attribute
= lttv_global_attributes();
95 LttvAttribute
*attribute
;
96 LttvAttributeType type
;
97 LttvAttributeName name
;
98 LttvAttributeValue value
;
101 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
104 type
= lttv_iattribute_get(LTTV_IATTRIBUTE(attribute
), num
, &name
, &value
);
106 if(type
== LTTV_POINTER
) {
107 return (LttvTrace
*)*(value
.v_pointer
);
113 /* Total number of traces */
115 guint
lttvwindowtraces_get_number()
117 LttvAttribute
*g_attribute
= lttv_global_attributes();
118 LttvAttribute
*attribute
;
119 LttvAttributeValue value
;
122 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
125 return ( lttv_iattribute_get_number(LTTV_IATTRIBUTE(attribute
)) );
128 /* Add a trace to the global attributes */
130 void lttvwindowtraces_add_trace(LttvTrace
*trace
)
132 LttvAttribute
*g_attribute
= lttv_global_attributes();
133 LttvAttribute
*attribute
;
134 LttvAttributeValue value
;
137 gchar attribute_path
[PATH_MAX
];
139 if(stat(ltt_trace_name(lttv_trace(trace
)), &buf
)) {
140 g_warning("lttvwindowtraces_add_trace: Trace %s not found",
141 ltt_trace_name(lttv_trace(trace
)));
145 snprintf(attribute_path
, PATH_MAX
, "%lu:%lu", buf
.st_dev
, buf
.st_ino
) >= 0);
148 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
151 value
= lttv_attribute_add(attribute
,
152 g_quark_from_string(attribute_path
),
155 *(value
.v_pointer
) = (gpointer
)trace
;
157 /* create new traceset and tracesetcontext */
159 LttvTracesetStats
*tss
;
161 attribute
= lttv_trace_attribute(trace
);
162 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
163 LTTV_COMPUTATION_TRACESET
,
166 ts
= lttv_traceset_new();
167 *(value
.v_pointer
) = ts
;
169 lttv_traceset_add(ts
,trace
);
171 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
172 LTTV_COMPUTATION_TRACESET_CONTEXT
,
175 tss
= g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
);
176 *(value
.v_pointer
) = tss
;
178 lttv_context_init(LTTV_TRACESET_CONTEXT(tss
), ts
);
180 value
= lttv_attribute_add(attribute
,
184 value
= lttv_attribute_add(attribute
,
185 LTTV_REQUESTS_CURRENT
,
188 value
= lttv_attribute_add(attribute
,
192 value
= lttv_attribute_add(attribute
,
198 /* Remove a trace from the global attributes */
200 void lttvwindowtraces_remove_trace(LttvTrace
*trace
)
202 LttvAttribute
*g_attribute
= lttv_global_attributes();
203 LttvAttribute
*attribute
;
204 LttvAttributeValue value
;
208 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
211 for(i
=0;i
<lttvwindowtraces_get_number();i
++) {
212 LttvTrace
*trace_v
= lttvwindowtraces_get_trace(i
);
214 g_assert(trace_v
!= NULL
);
216 /* Remove and background computation that could be in progress */
217 g_idle_remove_by_data(trace_v
);
219 if(trace_v
== trace
) {
221 LttvAttribute
*l_attribute
;
223 /* create new traceset and tracesetcontext */
225 LttvTracesetStats
*tss
;
227 l_attribute
= lttv_trace_attribute(trace
);
230 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
231 LTTV_REQUESTS_QUEUE
);
233 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
234 LTTV_REQUESTS_CURRENT
);
236 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
239 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
240 LTTV_NOTIFY_CURRENT
);
242 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(l_attribute
),
243 LTTV_COMPUTATION_TRACESET
,
246 ts
= (LttvTraceset
*)*(value
.v_pointer
);
248 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(l_attribute
),
249 LTTV_COMPUTATION_TRACESET_CONTEXT
,
252 tss
= (LttvTracesetStats
*)*(value
.v_pointer
);
254 lttv_context_fini(LTTV_TRACESET_CONTEXT(tss
));
256 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
257 LTTV_COMPUTATION_TRACESET_CONTEXT
);
258 lttv_traceset_destroy(ts
);
259 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
260 LTTV_COMPUTATION_TRACESET
);
262 /* finally, remove the global attribute */
263 lttv_attribute_remove(attribute
, i
);
272 * Function to request data from a specific trace
274 * The memory allocated for the request will be managed by the API.
276 * @param trace the trace to compute
277 * @param module_name the name of the module which registered global computation
281 void lttvwindowtraces_background_request_queue
282 (LttvTrace
*trace
, gchar
*module_name
)
284 BackgroundRequest
*bg_req
;
285 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
286 LttvAttributeValue value
;
290 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
294 slist
= (GSList
**)(value
.v_pointer
);
296 bg_req
= g_new(BackgroundRequest
,1);
297 bg_req
->module_name
= g_quark_from_string(module_name
);
298 bg_req
->trace
= trace
;
300 *slist
= g_slist_append(*slist
, bg_req
);
302 /* Priority lower than live servicing */
303 g_idle_remove_by_data(trace
);
304 g_idle_add_full((G_PRIORITY_HIGH_IDLE
+ 23),
305 (GSourceFunc
)lttvwindowtraces_process_pending_requests
,
308 /* FIXME : show message in status bar, need context and message id */
309 g_info("Background computation started for trace %p", trace
);
313 * Remove a background request from a trace.
315 * This should ONLY be used by the modules which registered the global hooks
316 * (module_name). If this is called by the viewers, it may lead to incomplete
317 * and incoherent background processing information.
319 * Even if the module which deals with the hooks removes the background
320 * requests, it may cause a problem if the module gets loaded again in the
321 * session : the data will be partially calculated. The calculation function
322 * must deal with this case correctly.
324 * @param trace the trace to compute
325 * @param module_name the name of the module which registered global computation
329 void lttvwindowtraces_background_request_remove
330 (LttvTrace
*trace
, gchar
*module_name
)
332 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
333 LttvAttributeValue value
;
337 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
341 slist
= (GSList
**)(value
.v_pointer
);
343 for(iter
=*slist
;iter
!=NULL
;) {
344 BackgroundRequest
*bg_req
=
345 (BackgroundRequest
*)iter
->data
;
347 if(bg_req
->module_name
== g_quark_from_string(module_name
)) {
348 GSList
*rem_iter
= iter
;
349 iter
=g_slist_next(iter
);
351 *slist
= g_slist_delete_link(*slist
, rem_iter
);
353 iter
=g_slist_next(iter
);
360 * Register a callback to be called when requested data is passed in the next
361 * queued background processing.
363 * @param owner owner of the background notification
364 * @param trace the trace computed
365 * @param notify_time time when notification hooks must be called
366 * @param notify_position position when notification hooks must be called
367 * @param notify Hook to call when the notify position is passed
370 void lttvwindowtraces_background_notify_queue
374 const LttvTracesetContextPosition
*notify_position
,
375 const LttvHooks
*notify
)
377 BackgroundNotify
*bg_notify
;
378 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
379 LttvAttributeValue value
;
382 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
386 slist
= (GSList
**)(value
.v_pointer
);
389 bg_notify
= g_new(BackgroundNotify
,1);
391 bg_notify
->owner
= owner
;
392 bg_notify
->trace
= trace
;
393 bg_notify
->notify_time
= notify_time
;
394 if(notify_position
!= NULL
) {
395 bg_notify
->notify_position
= lttv_traceset_context_position_new();
396 lttv_traceset_context_position_copy(bg_notify
->notify_position
,
399 bg_notify
->notify_position
= NULL
;
402 bg_notify
->notify
= lttv_hooks_new();
403 lttv_hooks_add_list(bg_notify
->notify
, notify
);
405 *slist
= g_slist_append(*slist
, bg_notify
);
409 * Register a callback to be called when requested data is passed in the current
410 * background processing.
412 * @param owner owner of the background notification
413 * @param trace the trace computed
414 * @param notify_time time when notification hooks must be called
415 * @param notify_position position when notification hooks must be called
416 * @param notify Hook to call when the notify position is passed
419 void lttvwindowtraces_background_notify_current
423 const LttvTracesetContextPosition
*notify_position
,
424 const LttvHooks
*notify
)
426 BackgroundNotify
*bg_notify
;
427 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
428 LttvAttributeValue value
;
431 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
435 slist
= (GSList
**)(value
.v_pointer
);
437 bg_notify
= g_new(BackgroundNotify
,1);
439 bg_notify
->owner
= owner
;
440 bg_notify
->trace
= trace
;
441 bg_notify
->notify_time
= notify_time
;
442 if(notify_position
!= NULL
) {
443 bg_notify
->notify_position
= lttv_traceset_context_position_new();
444 lttv_traceset_context_position_copy(bg_notify
->notify_position
,
447 bg_notify
->notify_position
= NULL
;
449 bg_notify
->notify
= lttv_hooks_new();
450 lttv_hooks_add_list(bg_notify
->notify
, notify
);
452 *slist
= g_slist_append(*slist
, bg_notify
);
456 static void notify_request_free(BackgroundNotify
*notify_req
)
458 if(notify_req
== NULL
) return;
460 if(notify_req
->notify_position
!= NULL
)
461 lttv_traceset_context_position_destroy(notify_req
->notify_position
);
462 if(notify_req
->notify
!= NULL
)
463 lttv_hooks_destroy(notify_req
->notify
);
468 * Removes all the notifications requests from a specific viewer.
470 * @param owner owner of the background notification
473 void lttvwindowtraces_background_notify_remove(gpointer owner
)
477 for(i
=0;i
<lttvwindowtraces_get_number();i
++) {
478 LttvAttribute
*attribute
;
479 LttvAttributeValue value
;
480 LttvTrace
*trace_v
= lttvwindowtraces_get_trace(i
);
484 g_assert(trace_v
!= NULL
);
486 attribute
= lttv_trace_attribute(trace_v
);
488 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
492 slist
= (GSList
**)(value
.v_pointer
);
494 for(iter
=*slist
;iter
!=NULL
;) {
496 BackgroundNotify
*bg_notify
= (BackgroundNotify
*)iter
->data
;
498 if(bg_notify
->owner
== owner
) {
499 GSList
*rem_iter
= iter
;
500 iter
=g_slist_next(iter
);
501 notify_request_free(bg_notify
);
502 *slist
= g_slist_remove_link(*slist
, rem_iter
);
504 iter
=g_slist_next(iter
);
508 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
512 slist
= (GSList
**)(value
.v_pointer
);
514 for(iter
=*slist
;iter
!=NULL
;) {
516 BackgroundNotify
*bg_notify
= (BackgroundNotify
*)iter
->data
;
518 if(bg_notify
->owner
== owner
) {
519 GSList
*rem_iter
= iter
;
520 iter
=g_slist_next(iter
);
521 notify_request_free(bg_notify
);
522 *slist
= g_slist_remove_link(*slist
, rem_iter
);
524 iter
=g_slist_next(iter
);
531 /* Background processing helper functions */
533 void lttvwindowtraces_add_computation_hooks(LttvAttributeName module_name
,
534 LttvTracesetContext
*tsc
)
536 LttvAttribute
*g_attribute
= lttv_global_attributes();
537 LttvAttribute
*module_attribute
;
538 LttvAttributeType type
;
539 LttvAttributeValue value
;
540 LttvHooks
*before_chunk_traceset
=NULL
;
541 LttvHooks
*before_chunk_trace
=NULL
;
542 LttvHooks
*before_chunk_tracefile
=NULL
;
543 LttvHooks
*event_hook
=NULL
;
544 LttvHooksById
*event_hook_by_id
=NULL
;
545 LttvTracesetStats
*tss
= LTTV_TRACESET_STATS(tsc
);
548 g_assert(module_attribute
=
549 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
552 g_assert(module_attribute
=
553 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
554 LTTV_IATTRIBUTE(module_attribute
),
557 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
558 LTTV_BEFORE_CHUNK_TRACESET
,
560 if(type
== LTTV_POINTER
) {
561 before_chunk_traceset
= (LttvHooks
*)*(value
.v_pointer
);
564 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
565 LTTV_BEFORE_CHUNK_TRACE
,
567 if(type
== LTTV_POINTER
) {
568 before_chunk_trace
= (LttvHooks
*)*(value
.v_pointer
);
571 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
572 LTTV_BEFORE_CHUNK_TRACEFILE
,
574 if(type
== LTTV_POINTER
) {
575 before_chunk_tracefile
= (LttvHooks
*)*(value
.v_pointer
);
578 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
581 if(type
== LTTV_POINTER
) {
582 event_hook
= (LttvHooks
*)*(value
.v_pointer
);
585 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
586 LTTV_EVENT_HOOK_BY_ID
,
588 if(type
== LTTV_POINTER
) {
589 event_hook_by_id
= (LttvHooksById
*)*(value
.v_pointer
);
592 /* Call the module's hook adder */
593 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
596 if(type
== LTTV_POINTER
) {
597 lttv_hooks_call((LttvHooks
*)*(value
.v_pointer
), (gpointer
)tss
);
602 lttv_process_traceset_begin(tsc
,
603 before_chunk_traceset
,
605 before_chunk_tracefile
,
611 void lttvwindowtraces_remove_computation_hooks(LttvAttributeName module_name
,
612 LttvTracesetContext
*tsc
)
614 LttvAttribute
*g_attribute
= lttv_global_attributes();
615 LttvAttribute
*module_attribute
;
616 LttvAttributeType type
;
617 LttvAttributeValue value
;
618 LttvHooks
*after_chunk_traceset
=NULL
;
619 LttvHooks
*after_chunk_trace
=NULL
;
620 LttvHooks
*after_chunk_tracefile
=NULL
;
621 LttvHooks
*event_hook
=NULL
;
622 LttvHooksById
*event_hook_by_id
=NULL
;
623 LttvTracesetStats
*tss
= LTTV_TRACESET_STATS(tsc
);
625 g_assert(module_attribute
=
626 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
629 g_assert(module_attribute
=
630 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
631 LTTV_IATTRIBUTE(module_attribute
),
634 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
635 LTTV_AFTER_CHUNK_TRACESET
,
637 if(type
== LTTV_POINTER
) {
638 after_chunk_traceset
= (LttvHooks
*)*(value
.v_pointer
);
641 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
642 LTTV_AFTER_CHUNK_TRACE
,
644 if(type
== LTTV_POINTER
) {
645 after_chunk_trace
= (LttvHooks
*)*(value
.v_pointer
);
648 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
649 LTTV_AFTER_CHUNK_TRACEFILE
,
651 if(type
== LTTV_POINTER
) {
652 after_chunk_tracefile
= (LttvHooks
*)*(value
.v_pointer
);
655 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
658 if(type
== LTTV_POINTER
) {
659 event_hook
= (LttvHooks
*)*(value
.v_pointer
);
662 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
663 LTTV_EVENT_HOOK_BY_ID
,
665 if(type
== LTTV_POINTER
) {
666 event_hook_by_id
= (LttvHooksById
*)*(value
.v_pointer
);
669 lttv_process_traceset_end(tsc
,
670 after_chunk_traceset
,
672 after_chunk_tracefile
,
676 /* Call the module's hook remover */
677 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
680 if(type
== LTTV_POINTER
) {
681 lttv_hooks_call((LttvHooks
*)*(value
.v_pointer
), (gpointer
)tss
);
686 void lttvwindowtraces_set_in_progress(LttvAttributeName module_name
,
689 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
690 LttvAttributeValue value
;
693 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
696 value
= lttv_iattribute_add(LTTV_IATTRIBUTE(attribute
),
699 /* the value is left unset. The only presence of the attribute is necessary.
703 void lttvwindowtraces_unset_in_progress(LttvAttributeName module_name
,
706 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
709 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
712 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
716 gboolean
lttvwindowtraces_get_in_progress(LttvAttributeName module_name
,
719 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
720 LttvAttributeType type
;
721 LttvAttributeValue value
;
724 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
727 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
730 /* The only presence of the attribute is necessary. */
731 if(type
== LTTV_NONE
)
737 void lttvwindowtraces_set_ready(LttvAttributeName module_name
,
740 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
741 LttvAttributeValue value
;
744 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
747 value
= lttv_iattribute_add(LTTV_IATTRIBUTE(attribute
),
750 /* the value is left unset. The only presence of the attribute is necessary.
754 void lttvwindowtraces_unset_ready(LttvAttributeName module_name
,
757 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
760 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
763 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
767 gboolean
lttvwindowtraces_get_ready(LttvAttributeName module_name
,
770 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
771 LttvAttributeType type
;
772 LttvAttributeValue value
;
775 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
778 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
781 /* The only presence of the attribute is necessary. */
782 if(type
== LTTV_NONE
)
789 /* lttvwindowtraces_process_pending_requests
791 * This internal function gets called by g_idle, taking care of the pending
797 gboolean
lttvwindowtraces_process_pending_requests(LttvTrace
*trace
)
799 LttvTracesetContext
*tsc
;
800 LttvTracesetStats
*tss
;
802 LttvAttribute
*attribute
;
803 GSList
**list_out
, **list_in
, **notify_in
, **notify_out
;
804 LttvAttributeValue value
;
805 LttvAttributeType type
;
811 attribute
= lttv_trace_attribute(trace
);
813 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
816 g_assert(type
== LTTV_POINTER
);
817 list_out
= (GSList
**)(value
.v_pointer
);
819 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
820 LTTV_REQUESTS_CURRENT
,
822 g_assert(type
== LTTV_POINTER
);
823 list_in
= (GSList
**)(value
.v_pointer
);
825 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
828 g_assert(type
== LTTV_POINTER
);
829 notify_out
= (GSList
**)(value
.v_pointer
);
831 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
834 g_assert(type
== LTTV_POINTER
);
835 notify_in
= (GSList
**)(value
.v_pointer
);
837 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
838 LTTV_COMPUTATION_TRACESET
,
840 g_assert(type
== LTTV_POINTER
);
841 ts
= (LttvTraceset
*)*(value
.v_pointer
);
843 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
844 LTTV_COMPUTATION_TRACESET_CONTEXT
,
846 g_assert(type
== LTTV_POINTER
);
847 tsc
= (LttvTracesetContext
*)*(value
.v_pointer
);
848 tss
= (LttvTracesetStats
*)*(value
.v_pointer
);
849 g_assert(LTTV_IS_TRACESET_CONTEXT(tsc
));
850 g_assert(LTTV_IS_TRACESET_STATS(tss
));
852 /* There is no events requests pending : we should never have been called! */
853 g_assert(g_slist_length(*list_out
) != 0 || g_slist_length(*list_in
) != 0);
855 /* 0.1 Lock traces */
860 iter_trace
<lttv_traceset_number(tsc
->ts
);
862 LttvTrace
*trace_v
= lttv_traceset_get(tsc
->ts
,iter_trace
);
864 if(lttvwindowtraces_lock(trace_v
) != 0)
865 return TRUE
; /* Cannot get trace lock, try later */
869 /* 0.2 Sync tracefiles */
870 lttv_process_traceset_synchronize_tracefiles(tsc
);
872 /* 1. Before processing */
874 /* if list_in is empty */
875 if(g_slist_length(*list_in
) == 0) {
878 /* - Add all requests in list_out to list_in, empty list_out */
879 GSList
*iter
= *list_out
;
881 while(iter
!= NULL
) {
882 gboolean remove
= FALSE
;
883 gboolean free_data
= FALSE
;
885 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
889 *list_in
= g_slist_append(*list_in
, bg_req
);
894 GSList
*remove_iter
= iter
;
896 iter
= g_slist_next(iter
);
897 if(free_data
) g_free(remove_iter
->data
);
898 *list_out
= g_slist_remove_link(*list_out
, remove_iter
);
899 } else { // not remove
900 iter
= g_slist_next(iter
);
906 GSList
*iter
= *list_in
;
907 /* - for each request in list_in */
908 while(iter
!= NULL
) {
910 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
911 /*- add hooks to context*/
912 lttvwindowtraces_set_in_progress(bg_req
->module_name
,
915 iter
= g_slist_next(iter
);
919 /* - seek trace to start */
921 LttTime start
= { 0, 0};
922 lttv_process_traceset_seek_time(tsc
, start
);
925 /* - Move all notifications from notify_out to notify_in. */
927 GSList
*iter
= *notify_out
;
928 g_assert(g_slist_length(*notify_in
) == 0);
930 while(iter
!= NULL
) {
931 gboolean remove
= FALSE
;
932 gboolean free_data
= FALSE
;
934 BackgroundNotify
*notify_req
= (BackgroundNotify
*)iter
->data
;
938 *notify_in
= g_slist_append(*notify_in
, notify_req
);
943 GSList
*remove_iter
= iter
;
945 iter
= g_slist_next(iter
);
947 notify_request_free((BackgroundNotify
*)remove_iter
->data
);
948 *notify_out
= g_slist_remove_link(*notify_out
, remove_iter
);
949 } else { // not remove
950 iter
= g_slist_next(iter
);
957 GSList
*iter
= *list_in
;
958 /* - for each request in list_in */
959 while(iter
!= NULL
) {
961 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
962 /*- Call before chunk hooks for list_in*/
963 /*- add hooks to context*/
964 lttvwindowtraces_add_computation_hooks(bg_req
->module_name
,
966 iter
= g_slist_next(iter
);
971 /* 2. call process traceset middle for a chunk */
973 /*(assert list_in is not empty! : should not even be called in that case)*/
974 LttTime end
= { G_MAXUINT
, G_MAXUINT
};
975 g_assert(g_slist_length(*list_in
) != 0);
977 lttv_process_traceset_middle(tsc
, end
, CHUNK_NUM_EVENTS
, NULL
);
980 /* 3. After the chunk */
982 /* 3.1 call after_chunk hooks for list_in */
984 GSList
*iter
= *list_in
;
985 /* - for each request in list_in */
986 while(iter
!= NULL
) {
988 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
989 /* - Call after chunk hooks for list_in */
990 /* - remove hooks from context */
991 lttvwindowtraces_remove_computation_hooks(bg_req
->module_name
,
993 iter
= g_slist_next(iter
);
997 /* 3.2 for each notify_in */
999 GSList
*iter
= *notify_in
;
1000 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
1002 while(iter
!= NULL
) {
1003 gboolean remove
= FALSE
;
1004 gboolean free_data
= FALSE
;
1006 BackgroundNotify
*notify_req
= (BackgroundNotify
*)iter
->data
;
1008 /* - if current time >= notify time, call notify and remove from
1010 * - if current position >= notify position, call notify and remove
1014 ltt_time_compare(notify_req
->notify_time
, tfc
->timestamp
) <= 0)
1016 (notify_req
->notify_position
!= NULL
&&
1017 lttv_traceset_context_ctx_pos_compare(tsc
,
1018 notify_req
->notify_position
) >= 0)
1021 lttv_hooks_call(notify_req
->notify
, notify_req
);
1030 GSList
*remove_iter
= iter
;
1032 iter
= g_slist_next(iter
);
1034 notify_request_free((BackgroundNotify
*)remove_iter
->data
);
1035 *notify_in
= g_slist_remove_link(*notify_in
, remove_iter
);
1036 } else { // not remove
1037 iter
= g_slist_next(iter
);
1043 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
1044 /* 3.3 if end of trace reached */
1046 g_debug("Current time : %lu sec, %lu nsec",
1047 tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1048 if(tfc
== NULL
|| ltt_time_compare(tfc
->timestamp
,
1049 tsc
->time_span
.end_time
) > 0) {
1051 /* - for each request in list_in */
1053 GSList
*iter
= *list_in
;
1055 while(iter
!= NULL
) {
1056 gboolean remove
= FALSE
;
1057 gboolean free_data
= FALSE
;
1059 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
1061 /* - set hooks'in_progress flag to FALSE */
1062 lttvwindowtraces_unset_in_progress(bg_req
->module_name
,
1064 /* - set hooks'ready flag to TRUE */
1065 lttvwindowtraces_set_ready(bg_req
->module_name
,
1067 /* - remove request */
1074 GSList
*remove_iter
= iter
;
1076 iter
= g_slist_next(iter
);
1077 if(free_data
) g_free(remove_iter
->data
);
1078 *list_in
= g_slist_remove_link(*list_in
, remove_iter
);
1079 } else { // not remove
1080 iter
= g_slist_next(iter
);
1085 /* - for each notifications in notify_in */
1087 GSList
*iter
= *notify_in
;
1089 while(iter
!= NULL
) {
1090 gboolean remove
= FALSE
;
1091 gboolean free_data
= FALSE
;
1093 BackgroundNotify
*notify_req
= (BackgroundNotify
*)iter
->data
;
1095 /* - call notify and remove from notify_in */
1096 lttv_hooks_call(notify_req
->notify
, notify_req
);
1103 GSList
*remove_iter
= iter
;
1105 iter
= g_slist_next(iter
);
1107 notify_request_free((BackgroundNotify
*)remove_iter
->data
);
1108 *notify_in
= g_slist_remove_link(*notify_in
, remove_iter
);
1109 } else { // not remove
1110 iter
= g_slist_next(iter
);
1115 /* - return FALSE (scheduler stopped) */
1116 g_debug("Background computation scheduler stopped");
1117 g_info("Background computation finished for trace %p", trace
);
1118 /* FIXME : remove status bar info, need context id and message id */
1121 /* 3.4 else, end of trace not reached */
1122 /* - return TRUE (scheduler still registered) */
1123 g_debug("Background computation left");
1128 /* 4. Unlock traces */
1130 //lttv_process_traceset_get_sync_data(tsc);
1134 iter_trace
<lttv_traceset_number(tsc
->ts
);
1136 LttvTrace
*trace_v
= lttv_traceset_get(tsc
->ts
, iter_trace
);
1138 lttvwindowtraces_unlock(trace_v
);
1147 * Register the background computation hooks for a specific module. It adds the
1148 * computation hooks to the global attrubutes, under "computation/module name".
1150 * @param module_name A GQuark : the name of the module which computes the
1153 void lttvwindowtraces_register_computation_hooks(LttvAttributeName module_name
,
1154 LttvHooks
*before_chunk_traceset
,
1155 LttvHooks
*before_chunk_trace
,
1156 LttvHooks
*before_chunk_tracefile
,
1157 LttvHooks
*after_chunk_traceset
,
1158 LttvHooks
*after_chunk_trace
,
1159 LttvHooks
*after_chunk_tracefile
,
1160 LttvHooks
*before_request
,
1161 LttvHooks
*after_request
,
1162 LttvHooks
*event_hook
,
1163 LttvHooksById
*event_hook_by_id
,
1164 LttvHooks
*hook_adder
,
1165 LttvHooks
*hook_remover
)
1167 LttvAttribute
*g_attribute
= lttv_global_attributes();
1168 LttvAttribute
*attribute
;
1169 LttvAttributeValue value
;
1171 g_assert(attribute
=
1172 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
1173 LTTV_COMPUTATION
)));
1175 g_assert(attribute
=
1176 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
1179 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1180 LTTV_BEFORE_CHUNK_TRACESET
,
1183 *(value
.v_pointer
) = before_chunk_traceset
;
1185 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1186 LTTV_BEFORE_CHUNK_TRACE
,
1189 *(value
.v_pointer
) = before_chunk_trace
;
1191 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1192 LTTV_BEFORE_CHUNK_TRACEFILE
,
1195 *(value
.v_pointer
) = before_chunk_tracefile
;
1197 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1198 LTTV_AFTER_CHUNK_TRACESET
,
1201 *(value
.v_pointer
) = after_chunk_traceset
;
1203 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1204 LTTV_AFTER_CHUNK_TRACE
,
1207 *(value
.v_pointer
) = after_chunk_trace
;
1209 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1210 LTTV_AFTER_CHUNK_TRACEFILE
,
1213 *(value
.v_pointer
) = after_chunk_tracefile
;
1215 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1216 LTTV_BEFORE_REQUEST
,
1219 *(value
.v_pointer
) = before_request
;
1221 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1225 *(value
.v_pointer
) = after_request
;
1227 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1231 *(value
.v_pointer
) = event_hook
;
1233 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1234 LTTV_EVENT_HOOK_BY_ID
,
1237 *(value
.v_pointer
) = event_hook_by_id
;
1239 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1243 *(value
.v_pointer
) = hook_adder
;
1245 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1249 *(value
.v_pointer
) = hook_remover
;
1255 * It removes all the requests than can be currently processed by the
1256 * background computation algorithm for all the traces (list_in and list_out).
1258 * Leaves the flag to in_progress or none.. depending if current or queue
1260 * @param module_name A GQuark : the name of the module which computes the
1263 void lttvwindowtraces_unregister_requests(LttvAttributeName module_name
)
1267 for(i
=0;i
<lttvwindowtraces_get_number();i
++) {
1268 LttvTrace
*trace_v
= lttvwindowtraces_get_trace(i
);
1269 g_assert(trace_v
!= NULL
);
1271 LttvAttribute
*attribute
= lttv_trace_attribute(trace_v
);
1272 LttvAttributeValue value
;
1273 GSList
**queue
, **current
;
1276 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1277 LTTV_REQUESTS_QUEUE
,
1280 queue
= (GSList
**)(value
.v_pointer
);
1283 while(iter
!= NULL
) {
1284 gboolean remove
= FALSE
;
1285 gboolean free_data
= FALSE
;
1287 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
1289 if(bg_req
->module_name
== module_name
) {
1297 GSList
*remove_iter
= iter
;
1299 iter
= g_slist_next(iter
);
1300 if(free_data
) g_free(remove_iter
->data
);
1301 *queue
= g_slist_remove_link(*queue
, remove_iter
);
1302 } else { // not remove
1303 iter
= g_slist_next(iter
);
1308 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1309 LTTV_REQUESTS_CURRENT
,
1312 current
= (GSList
**)(value
.v_pointer
);
1315 while(iter
!= NULL
) {
1316 gboolean remove
= FALSE
;
1317 gboolean free_data
= FALSE
;
1319 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
1321 if(bg_req
->module_name
== module_name
) {
1329 GSList
*remove_iter
= iter
;
1331 iter
= g_slist_next(iter
);
1332 if(free_data
) g_free(remove_iter
->data
);
1333 *current
= g_slist_remove_link(*current
, remove_iter
);
1334 } else { // not remove
1335 iter
= g_slist_next(iter
);
1343 * Unregister the background computation hooks for a specific module.
1345 * It also removes all the requests than can be currently processed by the
1346 * background computation algorithm for all the traces (list_in and list_out).
1348 * @param module_name A GQuark : the name of the module which computes the
1352 void lttvwindowtraces_unregister_computation_hooks
1353 (LttvAttributeName module_name
)
1355 LttvAttribute
*g_attribute
= lttv_global_attributes();
1356 LttvAttribute
*attribute
;
1358 g_assert(attribute
=
1359 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
1360 LTTV_COMPUTATION
)));
1361 g_assert(attribute
=
1362 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
1366 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1367 LTTV_EVENT_HOOK_BY_ID
);
1368 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1371 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1372 LTTV_AFTER_REQUEST
);
1373 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1374 LTTV_BEFORE_REQUEST
);
1376 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1377 LTTV_AFTER_CHUNK_TRACEFILE
);
1378 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1379 LTTV_AFTER_CHUNK_TRACE
);
1380 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1381 LTTV_AFTER_CHUNK_TRACESET
);
1383 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1384 LTTV_BEFORE_CHUNK_TRACEFILE
);
1385 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1386 LTTV_BEFORE_CHUNK_TRACE
);
1387 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1388 LTTV_BEFORE_CHUNK_TRACESET
);
1389 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1391 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1394 /* finally, remove module name */
1395 g_assert(attribute
=
1396 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
1397 LTTV_COMPUTATION
)));
1398 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1404 * Lock a trace so no other instance can use it.
1406 * @param trace The trace to lock.
1407 * @return 0 on success, -1 if cannot get lock.
1409 gint
lttvwindowtraces_lock(LttvTrace
*trace
)
1411 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
1412 LttvAttributeValue value
;
1413 LttvAttributeType type
;
1415 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
1418 /* Verify the absence of the lock. */
1419 if(type
!= LTTV_NONE
) {
1420 g_critical("Cannot take trace lock");
1424 value
= lttv_iattribute_add(LTTV_IATTRIBUTE(attribute
),
1427 /* the value is left unset. The only presence of the attribute is necessary.
1436 * @param trace The trace to unlock.
1437 * @return 0 on success, -1 if cannot unlock (not locked ?).
1439 gint
lttvwindowtraces_unlock(LttvTrace
*trace
)
1441 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
1442 LttvAttributeType type
;
1443 LttvAttributeValue value
;
1445 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
1448 /* Verify the presence of the lock. */
1449 if(type
== LTTV_NONE
) {
1450 g_critical("Cannot release trace lock");
1454 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1461 * Verify if a trace is locked.
1463 * @param trace The trace to verify.
1464 * @return TRUE if locked, FALSE is unlocked.
1466 gint
lttvwindowtraces_get_lock_state(LttvTrace
*trace
)
1468 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
1469 LttvAttributeType type
;
1470 LttvAttributeValue value
;
1472 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
1475 /* The only presence of the attribute is necessary. */
1476 if(type
== LTTV_NONE
)