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 if(trace_v
== trace
) {
218 LttvAttribute
*l_attribute
;
220 /* create new traceset and tracesetcontext */
222 LttvTracesetStats
*tss
;
224 l_attribute
= lttv_trace_attribute(trace
);
227 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
228 LTTV_REQUESTS_QUEUE
);
230 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
231 LTTV_REQUESTS_CURRENT
);
233 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
236 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
237 LTTV_NOTIFY_CURRENT
);
239 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(l_attribute
),
240 LTTV_COMPUTATION_TRACESET
,
243 ts
= (LttvTraceset
*)*(value
.v_pointer
);
245 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(l_attribute
),
246 LTTV_COMPUTATION_TRACESET_CONTEXT
,
249 tss
= (LttvTracesetStats
*)*(value
.v_pointer
);
251 lttv_context_fini(LTTV_TRACESET_CONTEXT(tss
));
253 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
254 LTTV_COMPUTATION_TRACESET_CONTEXT
);
255 lttv_traceset_destroy(ts
);
256 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute
),
257 LTTV_COMPUTATION_TRACESET
);
259 /* finally, remove the global attribute */
260 lttv_attribute_remove(attribute
, i
);
269 * Function to request data from a specific trace
271 * The memory allocated for the request will be managed by the API.
273 * @param trace the trace to compute
274 * @param module_name the name of the module which registered global computation
278 void lttvwindowtraces_background_request_queue
279 (LttvTrace
*trace
, gchar
*module_name
)
281 BackgroundRequest
*bg_req
;
282 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
283 LttvAttributeValue value
;
287 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
291 slist
= (GSList
**)(value
.v_pointer
);
293 bg_req
= g_new(BackgroundRequest
,1);
294 bg_req
->module_name
= g_quark_from_string(module_name
);
295 bg_req
->trace
= trace
;
297 *slist
= g_slist_append(*slist
, bg_req
);
299 /* Priority lower than live servicing */
300 g_idle_remove_by_data(trace
);
301 g_idle_add_full((G_PRIORITY_HIGH_IDLE
+ 23),
302 (GSourceFunc
)lttvwindowtraces_process_pending_requests
,
308 * Remove a background request from a trace.
310 * This should ONLY be used by the modules which registered the global hooks
311 * (module_name). If this is called by the viewers, it may lead to incomplete
312 * and incoherent background processing information.
314 * Even if the module which deals with the hooks removes the background
315 * requests, it may cause a problem if the module gets loaded again in the
316 * session : the data will be partially calculated. The calculation function
317 * must deal with this case correctly.
319 * @param trace the trace to compute
320 * @param module_name the name of the module which registered global computation
324 void lttvwindowtraces_background_request_remove
325 (LttvTrace
*trace
, gchar
*module_name
)
327 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
328 LttvAttributeValue value
;
332 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
336 slist
= (GSList
**)(value
.v_pointer
);
338 for(iter
=*slist
;iter
!=NULL
;) {
339 BackgroundRequest
*bg_req
=
340 (BackgroundRequest
*)iter
->data
;
342 if(bg_req
->module_name
== g_quark_from_string(module_name
)) {
343 GSList
*rem_iter
= iter
;
344 iter
=g_slist_next(iter
);
346 *slist
= g_slist_delete_link(*slist
, rem_iter
);
348 iter
=g_slist_next(iter
);
355 * Register a callback to be called when requested data is passed in the next
356 * queued background processing.
358 * @param owner owner of the background notification
359 * @param trace the trace computed
360 * @param notify_time time when notification hooks must be called
361 * @param notify_position position when notification hooks must be called
362 * @param notify Hook to call when the notify position is passed
365 void lttvwindowtraces_background_notify_queue
369 const LttvTracesetContextPosition
*notify_position
,
370 const LttvHooks
*notify
)
372 BackgroundNotify
*bg_notify
;
373 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
374 LttvAttributeValue value
;
377 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
381 slist
= (GSList
**)(value
.v_pointer
);
384 bg_notify
= g_new(BackgroundNotify
,1);
386 bg_notify
->owner
= owner
;
387 bg_notify
->trace
= trace
;
388 bg_notify
->notify_time
= notify_time
;
389 if(notify_position
!= NULL
) {
390 bg_notify
->notify_position
= ltt_traceset_context_position_new();
391 lttv_traceset_context_position_copy(bg_notify
->notify_position
,
394 bg_notify
->notify_position
= NULL
;
397 bg_notify
->notify
= lttv_hooks_new();
398 lttv_hooks_add_list(bg_notify
->notify
, notify
);
400 *slist
= g_slist_append(*slist
, bg_notify
);
404 * Register a callback to be called when requested data is passed in the current
405 * background processing.
407 * @param owner owner of the background notification
408 * @param trace the trace computed
409 * @param notify_time time when notification hooks must be called
410 * @param notify_position position when notification hooks must be called
411 * @param notify Hook to call when the notify position is passed
414 void lttvwindowtraces_background_notify_current
418 const LttvTracesetContextPosition
*notify_position
,
419 const LttvHooks
*notify
)
421 BackgroundNotify
*bg_notify
;
422 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
423 LttvAttributeValue value
;
426 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
430 slist
= (GSList
**)(value
.v_pointer
);
432 bg_notify
= g_new(BackgroundNotify
,1);
434 bg_notify
->owner
= owner
;
435 bg_notify
->trace
= trace
;
436 bg_notify
->notify_time
= notify_time
;
437 if(notify_position
!= NULL
) {
438 bg_notify
->notify_position
= ltt_traceset_context_position_new();
439 lttv_traceset_context_position_copy(bg_notify
->notify_position
,
442 bg_notify
->notify_position
= NULL
;
444 bg_notify
->notify
= lttv_hooks_new();
445 lttv_hooks_add_list(bg_notify
->notify
, notify
);
447 *slist
= g_slist_append(*slist
, bg_notify
);
451 * Removes all the notifications requests from a specific viewer.
453 * @param owner owner of the background notification
456 void lttvwindowtraces_background_notify_remove(gpointer owner
)
460 for(i
=0;i
<lttvwindowtraces_get_number();i
++) {
461 LttvAttribute
*attribute
;
462 LttvAttributeValue value
;
463 LttvTrace
*trace_v
= lttvwindowtraces_get_trace(i
);
467 g_assert(trace_v
!= NULL
);
469 LttvAttribute
*t_a
= lttv_trace_attribute(trace_v
);
471 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
475 slist
= (GSList
**)(value
.v_pointer
);
477 for(iter
=*slist
;iter
!=NULL
;) {
479 BackgroundNotify
*bg_notify
= (BackgroundNotify
*)iter
->data
;
481 if(bg_notify
->owner
== owner
) {
482 GSList
*rem_iter
= iter
;
483 iter
=g_slist_next(iter
);
484 if(bg_notify
->notify_position
!= NULL
)
485 lttv_traceset_context_position_destroy(
486 bg_notify
->notify_position
);
487 lttv_hooks_destroy(bg_notify
->notify
);
489 g_slist_remove_link(*slist
, rem_iter
);
491 iter
=g_slist_next(iter
);
495 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
499 slist
= (GSList
**)(value
.v_pointer
);
501 for(iter
=*slist
;iter
!=NULL
;) {
503 BackgroundNotify
*bg_notify
= (BackgroundNotify
*)iter
->data
;
505 if(bg_notify
->owner
== owner
) {
506 GSList
*rem_iter
= iter
;
507 iter
=g_slist_next(iter
);
508 if(bg_notify
->notify_position
!= NULL
)
509 lttv_traceset_context_position_destroy(
510 bg_notify
->notify_position
);
511 lttv_hooks_destroy(bg_notify
->notify
);
513 g_slist_remove_link(*slist
, rem_iter
);
515 iter
=g_slist_next(iter
);
522 /* Background processing helper functions */
524 void lttvwindowtraces_add_computation_hooks(LttvAttributeName module_name
,
525 LttvTracesetContext
*tsc
)
527 LttvAttribute
*g_attribute
= lttv_global_attributes();
528 LttvAttribute
*module_attribute
;
529 LttvAttributeType type
;
530 LttvAttributeValue value
;
531 LttvHooks
*before_chunk_traceset
=NULL
;
532 LttvHooks
*before_chunk_trace
=NULL
;
533 LttvHooks
*before_chunk_tracefile
=NULL
;
534 LttvHooks
*event_hook
=NULL
;
535 LttvHooksById
*event_hook_by_id
=NULL
;
536 LttvTracesetStats
*tss
= LTTV_TRACESET_STATS(tsc
);
539 g_assert(module_attribute
=
540 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
543 g_assert(module_attribute
=
544 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
545 LTTV_IATTRIBUTE(module_attribute
),
548 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
549 LTTV_BEFORE_CHUNK_TRACESET
,
551 if(type
== LTTV_POINTER
) {
552 before_chunk_traceset
= (LttvHooks
*)*(value
.v_pointer
);
555 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
556 LTTV_BEFORE_CHUNK_TRACE
,
558 if(type
== LTTV_POINTER
) {
559 before_chunk_trace
= (LttvHooks
*)*(value
.v_pointer
);
562 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
563 LTTV_BEFORE_CHUNK_TRACEFILE
,
565 if(type
== LTTV_POINTER
) {
566 before_chunk_tracefile
= (LttvHooks
*)*(value
.v_pointer
);
569 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
572 if(type
== LTTV_POINTER
) {
573 event_hook
= (LttvHooks
*)*(value
.v_pointer
);
576 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
577 LTTV_EVENT_HOOK_BY_ID
,
579 if(type
== LTTV_POINTER
) {
580 event_hook_by_id
= (LttvHooksById
*)*(value
.v_pointer
);
583 /* Call the module's hook adder */
584 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
587 if(type
== LTTV_POINTER
) {
588 lttv_hooks_call((LttvHooks
*)*(value
.v_pointer
), (gpointer
)tss
);
593 lttv_process_traceset_begin(tsc
,
594 before_chunk_traceset
,
596 before_chunk_tracefile
,
602 void lttvwindowtraces_remove_computation_hooks(LttvAttributeName module_name
,
603 LttvTracesetContext
*tsc
)
605 LttvAttribute
*g_attribute
= lttv_global_attributes();
606 LttvAttribute
*module_attribute
;
607 LttvAttributeType type
;
608 LttvAttributeValue value
;
609 LttvHooks
*after_chunk_traceset
=NULL
;
610 LttvHooks
*after_chunk_trace
=NULL
;
611 LttvHooks
*after_chunk_tracefile
=NULL
;
612 LttvHooks
*event_hook
=NULL
;
613 LttvHooksById
*event_hook_by_id
=NULL
;
614 LttvTracesetStats
*tss
= LTTV_TRACESET_STATS(tsc
);
616 g_assert(module_attribute
=
617 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
620 g_assert(module_attribute
=
621 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
622 LTTV_IATTRIBUTE(module_attribute
),
625 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
626 LTTV_AFTER_CHUNK_TRACESET
,
628 if(type
== LTTV_POINTER
) {
629 after_chunk_traceset
= (LttvHooks
*)*(value
.v_pointer
);
632 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
633 LTTV_AFTER_CHUNK_TRACE
,
635 if(type
== LTTV_POINTER
) {
636 after_chunk_trace
= (LttvHooks
*)*(value
.v_pointer
);
639 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
640 LTTV_AFTER_CHUNK_TRACEFILE
,
642 if(type
== LTTV_POINTER
) {
643 after_chunk_tracefile
= (LttvHooks
*)*(value
.v_pointer
);
646 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
649 if(type
== LTTV_POINTER
) {
650 event_hook
= (LttvHooks
*)*(value
.v_pointer
);
653 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
654 LTTV_EVENT_HOOK_BY_ID
,
656 if(type
== LTTV_POINTER
) {
657 event_hook_by_id
= (LttvHooksById
*)*(value
.v_pointer
);
660 lttv_process_traceset_end(tsc
,
661 after_chunk_traceset
,
663 after_chunk_tracefile
,
667 /* Call the module's hook remover */
668 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute
),
671 if(type
== LTTV_POINTER
) {
672 lttv_hooks_call((LttvHooks
*)*(value
.v_pointer
), (gpointer
)tss
);
677 void lttvwindowtraces_set_in_progress(LttvAttributeName module_name
,
680 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
681 LttvAttributeValue value
;
684 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
687 value
= lttv_iattribute_add(LTTV_IATTRIBUTE(attribute
),
690 /* the value is left unset. The only presence of the attribute is necessary.
694 void lttvwindowtraces_unset_in_progress(LttvAttributeName module_name
,
697 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
700 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
703 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
707 gboolean
lttvwindowtraces_get_in_progress(LttvAttributeName module_name
,
710 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
711 LttvAttributeType type
;
712 LttvAttributeValue value
;
715 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
718 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
721 /* The only presence of the attribute is necessary. */
722 if(type
== LTTV_NONE
)
728 void lttvwindowtraces_set_ready(LttvAttributeName module_name
,
731 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
732 LttvAttributeValue value
;
735 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
738 value
= lttv_iattribute_add(LTTV_IATTRIBUTE(attribute
),
741 /* the value is left unset. The only presence of the attribute is necessary.
745 void lttvwindowtraces_unset_ready(LttvAttributeName module_name
,
748 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
751 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
754 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
758 gboolean
lttvwindowtraces_get_ready(LttvAttributeName module_name
,
761 LttvAttribute
*attribute
= lttv_trace_attribute(trace
);
762 LttvAttributeType type
;
763 LttvAttributeValue value
;
766 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
769 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
772 /* The only presence of the attribute is necessary. */
773 if(type
== LTTV_NONE
)
781 /* lttvwindowtraces_process_pending_requests
783 * This internal function gets called by g_idle, taking care of the pending
789 gboolean
lttvwindowtraces_process_pending_requests(LttvTrace
*trace
)
791 LttvTracesetContext
*tsc
;
792 LttvTracesetStats
*tss
;
794 LttvAttribute
*attribute
;
795 GSList
**list_out
, **list_in
, **notify_in
, **notify_out
;
796 LttvAttributeValue value
;
797 LttvAttributeType type
;
802 attribute
= lttv_trace_attribute(trace
);
804 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
807 g_assert(type
== LTTV_POINTER
);
808 list_out
= (GSList
**)(value
.v_pointer
);
810 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
811 LTTV_REQUESTS_CURRENT
,
813 g_assert(type
== LTTV_POINTER
);
814 list_in
= (GSList
**)(value
.v_pointer
);
816 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
819 g_assert(type
== LTTV_POINTER
);
820 notify_out
= (GSList
**)(value
.v_pointer
);
822 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
825 g_assert(type
== LTTV_POINTER
);
826 notify_in
= (GSList
**)(value
.v_pointer
);
828 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
829 LTTV_COMPUTATION_TRACESET
,
831 g_assert(type
== LTTV_POINTER
);
832 ts
= (LttvTraceset
*)*(value
.v_pointer
);
834 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
835 LTTV_COMPUTATION_TRACESET_CONTEXT
,
837 g_assert(type
== LTTV_POINTER
);
838 tsc
= (LttvTracesetContext
*)*(value
.v_pointer
);
839 tss
= (LttvTracesetStats
*)*(value
.v_pointer
);
840 g_assert(LTTV_IS_TRACESET_CONTEXT(tsc
));
841 g_assert(LTTV_IS_TRACESET_STATS(tss
));
843 /* There is no events requests pending : we should never have been called! */
844 g_assert(g_slist_length(*list_out
) != 0 || g_slist_length(*list_in
) != 0);
848 /* 1. Before processing */
850 /* if list_in is empty */
851 if(g_slist_length(*list_in
) == 0) {
854 /* - Add all requests in list_out to list_in, empty list_out */
855 GSList
*iter
= *list_out
;
857 while(iter
!= NULL
) {
858 gboolean remove
= FALSE
;
859 gboolean free_data
= FALSE
;
861 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
865 *list_in
= g_slist_append(*list_in
, bg_req
);
870 GSList
*remove_iter
= iter
;
872 iter
= g_slist_next(iter
);
873 if(free_data
) g_free(remove_iter
->data
);
874 *list_out
= g_slist_remove_link(*list_out
, remove_iter
);
875 } else { // not remove
876 iter
= g_slist_next(iter
);
882 GSList
*iter
= *list_in
;
883 /* - for each request in list_in */
884 while(iter
!= NULL
) {
886 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
887 /*- add hooks to context*/
888 lttvwindowtraces_set_in_progress(bg_req
->module_name
,
891 iter
= g_slist_next(iter
);
895 /* - seek trace to start */
897 LttTime start
= { 0, 0};
898 lttv_process_traceset_seek_time(tsc
, start
);
901 /* - Move all notifications from notify_out to notify_in. */
903 GSList
*iter
= *notify_out
;
904 g_assert(g_slist_length(*notify_in
) == 0);
906 while(iter
!= NULL
) {
907 gboolean remove
= FALSE
;
908 gboolean free_data
= FALSE
;
910 BackgroundNotify
*notify_req
= (BackgroundNotify
*)iter
->data
;
914 *notify_in
= g_slist_append(*notify_in
, notify_req
);
919 GSList
*remove_iter
= iter
;
921 iter
= g_slist_next(iter
);
922 if(free_data
) g_free(remove_iter
->data
);
923 *notify_out
= g_slist_remove_link(*notify_out
, remove_iter
);
924 } else { // not remove
925 iter
= g_slist_next(iter
);
932 GSList
*iter
= *list_in
;
933 /* - for each request in list_in */
934 while(iter
!= NULL
) {
936 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
937 /*- Call before chunk hooks for list_in*/
938 /*- add hooks to context*/
939 lttvwindowtraces_add_computation_hooks(bg_req
->module_name
,
941 iter
= g_slist_next(iter
);
946 /* 2. call process traceset middle for a chunk */
948 /*(assert list_in is not empty! : should not even be called in that case)*/
949 LttTime end
= { G_MAXUINT
, G_MAXUINT
};
950 g_assert(g_slist_length(*list_in
) != 0);
952 lttv_process_traceset_middle(tsc
, end
, CHUNK_NUM_EVENTS
, NULL
);
955 /* 3. After the chunk */
957 /* 3.1 call after_chunk hooks for list_in */
959 GSList
*iter
= *list_in
;
960 /* - for each request in list_in */
961 while(iter
!= NULL
) {
963 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
964 /* - Call after chunk hooks for list_in */
965 /* - remove hooks from context */
966 lttvwindowtraces_remove_computation_hooks(bg_req
->module_name
,
968 iter
= g_slist_next(iter
);
972 /* 3.2 for each notify_in */
974 GSList
*iter
= *notify_in
;
975 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
977 while(iter
!= NULL
) {
978 gboolean remove
= FALSE
;
979 gboolean free_data
= FALSE
;
981 BackgroundNotify
*notify_req
= (BackgroundNotify
*)iter
->data
;
983 /* - if current time >= notify time, call notify and remove from
985 * - if current position >= notify position, call notify and remove
989 ltt_time_compare(notify_req
->notify_time
, tfc
->timestamp
) <= 0)
991 (notify_req
->notify_position
!= NULL
&&
992 lttv_traceset_context_ctx_pos_compare(tsc
,
993 notify_req
->notify_position
) >= 0)
996 lttv_hooks_call(notify_req
->notify
, notify_req
);
1005 GSList
*remove_iter
= iter
;
1007 iter
= g_slist_next(iter
);
1008 if(free_data
) g_free(remove_iter
->data
);
1009 *notify_in
= g_slist_remove_link(*notify_in
, remove_iter
);
1010 } else { // not remove
1011 iter
= g_slist_next(iter
);
1017 LttvTracefileContext
*tfc
= lttv_traceset_context_get_current_tfc(tsc
);
1018 /* 3.3 if end of trace reached */
1020 g_debug("Current time : %lu sec, %lu nsec",
1021 tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1022 if(tfc
== NULL
|| ltt_time_compare(tfc
->timestamp
,
1023 tsc
->time_span
.end_time
) > 0) {
1025 /* - for each request in list_in */
1027 GSList
*iter
= *list_in
;
1029 while(iter
!= NULL
) {
1030 gboolean remove
= FALSE
;
1031 gboolean free_data
= FALSE
;
1033 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
1035 /* - set hooks'in_progress flag to FALSE */
1036 lttvwindowtraces_unset_in_progress(bg_req
->module_name
,
1038 /* - set hooks'ready flag to TRUE */
1039 lttvwindowtraces_set_ready(bg_req
->module_name
,
1041 /* - remove request */
1048 GSList
*remove_iter
= iter
;
1050 iter
= g_slist_next(iter
);
1051 if(free_data
) g_free(remove_iter
->data
);
1052 *list_in
= g_slist_remove_link(*list_in
, remove_iter
);
1053 } else { // not remove
1054 iter
= g_slist_next(iter
);
1059 /* - for each notifications in notify_in */
1061 GSList
*iter
= *notify_in
;
1063 while(iter
!= NULL
) {
1064 gboolean remove
= FALSE
;
1065 gboolean free_data
= FALSE
;
1067 BackgroundNotify
*notify_req
= (BackgroundNotify
*)iter
->data
;
1069 /* - call notify and remove from notify_in */
1070 lttv_hooks_call(notify_req
->notify
, notify_req
);
1077 GSList
*remove_iter
= iter
;
1079 iter
= g_slist_next(iter
);
1080 if(free_data
) g_free(remove_iter
->data
);
1081 *notify_in
= g_slist_remove_link(*notify_in
, remove_iter
);
1082 } else { // not remove
1083 iter
= g_slist_next(iter
);
1088 /* - return FALSE (scheduler stopped) */
1089 g_debug("Background computation scheduler stopped");
1092 /* 3.4 else, end of trace not reached */
1093 /* - return TRUE (scheduler still registered) */
1094 g_debug("Background computation left");
1104 * Register the background computation hooks for a specific module. It adds the
1105 * computation hooks to the global attrubutes, under "computation/module name".
1107 * @param module_name A GQuark : the name of the module which computes the
1110 void lttvwindowtraces_register_computation_hooks(LttvAttributeName module_name
,
1111 LttvHooks
*before_chunk_traceset
,
1112 LttvHooks
*before_chunk_trace
,
1113 LttvHooks
*before_chunk_tracefile
,
1114 LttvHooks
*after_chunk_traceset
,
1115 LttvHooks
*after_chunk_trace
,
1116 LttvHooks
*after_chunk_tracefile
,
1117 LttvHooks
*before_request
,
1118 LttvHooks
*after_request
,
1119 LttvHooks
*event_hook
,
1120 LttvHooksById
*event_hook_by_id
,
1121 LttvHooks
*hook_adder
,
1122 LttvHooks
*hook_remover
)
1124 LttvAttribute
*g_attribute
= lttv_global_attributes();
1125 LttvAttribute
*attribute
;
1126 LttvAttributeValue value
;
1128 g_assert(attribute
=
1129 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
1130 LTTV_COMPUTATION
)));
1132 g_assert(attribute
=
1133 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
1136 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1137 LTTV_BEFORE_CHUNK_TRACESET
,
1140 *(value
.v_pointer
) = before_chunk_traceset
;
1142 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1143 LTTV_BEFORE_CHUNK_TRACE
,
1146 *(value
.v_pointer
) = before_chunk_trace
;
1148 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1149 LTTV_BEFORE_CHUNK_TRACEFILE
,
1152 *(value
.v_pointer
) = before_chunk_tracefile
;
1154 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1155 LTTV_AFTER_CHUNK_TRACESET
,
1158 *(value
.v_pointer
) = after_chunk_traceset
;
1160 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1161 LTTV_AFTER_CHUNK_TRACE
,
1164 *(value
.v_pointer
) = after_chunk_trace
;
1166 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1167 LTTV_AFTER_CHUNK_TRACEFILE
,
1170 *(value
.v_pointer
) = after_chunk_tracefile
;
1172 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1173 LTTV_BEFORE_REQUEST
,
1176 *(value
.v_pointer
) = before_request
;
1178 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1182 *(value
.v_pointer
) = after_request
;
1184 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1188 *(value
.v_pointer
) = event_hook
;
1190 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1191 LTTV_EVENT_HOOK_BY_ID
,
1194 *(value
.v_pointer
) = event_hook_by_id
;
1196 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1200 *(value
.v_pointer
) = hook_adder
;
1202 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1206 *(value
.v_pointer
) = hook_remover
;
1212 * It removes all the requests than can be currently processed by the
1213 * background computation algorithm for all the traces (list_in and list_out).
1215 * Leaves the flag to in_progress or none.. depending if current or queue
1217 * @param module_name A GQuark : the name of the module which computes the
1220 void lttvwindowtraces_unregister_requests(LttvAttributeName module_name
)
1224 for(i
=0;i
<lttvwindowtraces_get_number();i
++) {
1225 LttvTrace
*trace_v
= lttvwindowtraces_get_trace(i
);
1226 g_assert(trace_v
!= NULL
);
1228 LttvAttribute
*attribute
= lttv_trace_attribute(trace_v
);
1229 LttvAttributeValue value
;
1230 GSList
**queue
, **current
;
1233 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1234 LTTV_REQUESTS_QUEUE
,
1237 queue
= (GSList
**)(value
.v_pointer
);
1240 while(iter
!= NULL
) {
1241 gboolean remove
= FALSE
;
1242 gboolean free_data
= FALSE
;
1244 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
1246 if(bg_req
->module_name
== module_name
) {
1254 GSList
*remove_iter
= iter
;
1256 iter
= g_slist_next(iter
);
1257 if(free_data
) g_free(remove_iter
->data
);
1258 *queue
= g_slist_remove_link(*queue
, remove_iter
);
1259 } else { // not remove
1260 iter
= g_slist_next(iter
);
1265 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute
),
1266 LTTV_REQUESTS_CURRENT
,
1269 current
= (GSList
**)(value
.v_pointer
);
1272 while(iter
!= NULL
) {
1273 gboolean remove
= FALSE
;
1274 gboolean free_data
= FALSE
;
1276 BackgroundRequest
*bg_req
= (BackgroundRequest
*)iter
->data
;
1278 if(bg_req
->module_name
== module_name
) {
1286 GSList
*remove_iter
= iter
;
1288 iter
= g_slist_next(iter
);
1289 if(free_data
) g_free(remove_iter
->data
);
1290 *current
= g_slist_remove_link(*current
, remove_iter
);
1291 } else { // not remove
1292 iter
= g_slist_next(iter
);
1300 * Unregister the background computation hooks for a specific module.
1302 * It also removes all the requests than can be currently processed by the
1303 * background computation algorithm for all the traces (list_in and list_out).
1305 * @param module_name A GQuark : the name of the module which computes the
1309 void lttvwindowtraces_unregister_computation_hooks
1310 (LttvAttributeName module_name
)
1312 LttvAttribute
*g_attribute
= lttv_global_attributes();
1313 LttvAttribute
*attribute
;
1315 g_assert(attribute
=
1316 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
1317 LTTV_COMPUTATION
)));
1318 g_assert(attribute
=
1319 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute
),
1323 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1324 LTTV_EVENT_HOOK_BY_ID
);
1325 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1328 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1329 LTTV_AFTER_REQUEST
);
1330 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1331 LTTV_BEFORE_REQUEST
);
1333 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1334 LTTV_AFTER_CHUNK_TRACEFILE
);
1335 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1336 LTTV_AFTER_CHUNK_TRACE
);
1337 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1338 LTTV_AFTER_CHUNK_TRACESET
);
1340 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1341 LTTV_BEFORE_CHUNK_TRACEFILE
);
1342 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1343 LTTV_BEFORE_CHUNK_TRACE
);
1344 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1345 LTTV_BEFORE_CHUNK_TRACESET
);
1346 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1348 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),
1351 /* finally, remove module name */
1352 g_assert(attribute
=
1353 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute
),
1354 LTTV_COMPUTATION
)));
1355 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute
),