background computation for control flow viewer
[lttv.git] / ltt / branches / poly / lttv / modules / gui / lttvwindow / lttvwindow / lttvwindowtraces.c
CommitLineData
a1a2b649 1/* This file is part of the Linux Trace Toolkit Graphic User Interface
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
3 *
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;
7 *
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.
12 *
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,
16 * MA 02111-1307, USA.
17 */
18
19/* This file is the API used to launch any background computation on a trace */
20
21/* Here is the implementation of the API */
22
0fdb8bb0 23#include <sys/types.h>
24#include <sys/stat.h>
25#include <unistd.h>
26
a1a2b649 27#include <ltt/time.h>
28#include <ltt/trace.h>
29#include <glib.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>
8bc02ec8 35#include <lttvwindow/lttvwindow.h> // for CHUNK_NUM_EVENTS
a1a2b649 36
37
38typedef struct _BackgroundRequest {
39 LttvAttributeName module_name; /* Hook path in global attributes,
40 where all standard hooks under computation/.
41 i.e. modulename */
42 LttvTrace *trace; /* trace concerned */
43} BackgroundRequest;
44
45typedef struct _BackgroundNotify {
46 gpointer owner;
47 LttvTrace *trace; /* trace */
48 LttTime notify_time;
49 LttvTracesetContextPosition *notify_position;
50 LttvHooks *notify; /* Hook to call when the notify is
51 passed, or at the end of trace */
52} BackgroundNotify;
53
54
55
56/* Get a trace by its path name.
57 *
58 * @param path path of the trace on the virtual file system.
59 * @return Pointer to trace if found
60 * NULL is returned if the trace is not present
61 */
62
63LttvTrace *lttvwindowtraces_get_trace_by_name(gchar *path)
64{
65 LttvAttribute *attribute = lttv_global_attributes();
66 guint i;
67
68 for(i=0;i<lttvwindowtraces_get_number();i++) {
69 LttvTrace *trace_v = lttvwindowtraces_get_trace(i);
70 LttTrace *trace;
71 gchar *name;
a1a2b649 72 g_assert(trace_v != NULL);
73
74 trace = lttv_trace(trace_v);
75 g_assert(trace != NULL);
76 name = ltt_trace_name(trace);
77
78 if(strcmp(name, path) == 0) {
79 /* Found */
80 return trace_v;
81 }
82 }
83
84 return NULL;
85}
86
87/* Get a trace by its number identifier */
88
89LttvTrace *lttvwindowtraces_get_trace(guint num)
90{
91 LttvAttribute *g_attribute = lttv_global_attributes();
92 LttvAttribute *attribute;
93 LttvAttributeType type;
94 LttvAttributeName name;
95 LttvAttributeValue value;
96
97 g_assert(attribute =
98 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
99 LTTV_TRACES)));
100
101 type = lttv_iattribute_get(LTTV_IATTRIBUTE(attribute), num, &name, &value);
102
103 if(type == LTTV_POINTER) {
104 return (LttvTrace *)*(value.v_pointer);
105 }
106
107 return NULL;
108}
109
110/* Total number of traces */
111
112guint lttvwindowtraces_get_number()
113{
114 LttvAttribute *g_attribute = lttv_global_attributes();
115 LttvAttribute *attribute;
116 LttvAttributeValue value;
117
118 g_assert(attribute =
119 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
120 LTTV_TRACES)));
121
122 return ( lttv_iattribute_get_number(LTTV_IATTRIBUTE(attribute)) );
123}
124
125/* Add a trace to the global attributes */
126
127void lttvwindowtraces_add_trace(LttvTrace *trace)
128{
129 LttvAttribute *g_attribute = lttv_global_attributes();
130 LttvAttribute *attribute;
131 LttvAttributeValue value;
132 guint num;
0fdb8bb0 133 struct stat buf;
134 gchar attribute_path[PATH_MAX];
a1a2b649 135
0fdb8bb0 136 if(stat(ltt_trace_name(lttv_trace(trace)), &buf)) {
137 g_warning("lttvwindowtraces_add_trace: Trace %s not found",
138 ltt_trace_name(lttv_trace(trace)));
139 return;
140 }
141 g_assert(
142 snprintf(attribute_path, PATH_MAX, "%lu:%lu", buf.st_dev, buf.st_ino) >= 0);
143
a1a2b649 144 g_assert(attribute =
145 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
146 LTTV_TRACES)));
0fdb8bb0 147
a1a2b649 148 value = lttv_attribute_add(attribute,
0fdb8bb0 149 g_quark_from_string(attribute_path),
a1a2b649 150 LTTV_POINTER);
151
152 *(value.v_pointer) = (gpointer)trace;
8bc02ec8 153
154 /* create new traceset and tracesetcontext */
155 LttvTraceset *ts;
156 LttvTracesetContext *tsc;
157
158 attribute = lttv_trace_attribute(trace);
159 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
160 LTTV_COMPUTATION_TRACESET,
161 LTTV_POINTER,
162 &value));
163 ts = lttv_traceset_new();
164 *(value.v_pointer) = ts;
165
166 lttv_traceset_add(ts,trace);
167
168 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
169 LTTV_COMPUTATION_TRACESET_CONTEXT,
170 LTTV_POINTER,
171 &value));
172 tsc = g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
173 *(value.v_pointer) = tsc;
174
175 lttv_context_init(tsc, ts);
176
177 value = lttv_attribute_add(attribute,
178 LTTV_REQUESTS_QUEUE,
179 LTTV_POINTER);
180
181 value = lttv_attribute_add(attribute,
182 LTTV_REQUESTS_CURRENT,
183 LTTV_POINTER);
184
185 value = lttv_attribute_add(attribute,
186 LTTV_NOTIFY_QUEUE,
187 LTTV_POINTER);
188
189 value = lttv_attribute_add(attribute,
190 LTTV_NOTIFY_CURRENT,
191 LTTV_POINTER);
192
a1a2b649 193}
194
195/* Remove a trace from the global attributes */
196
197void lttvwindowtraces_remove_trace(LttvTrace *trace)
198{
199 LttvAttribute *g_attribute = lttv_global_attributes();
200 LttvAttribute *attribute;
201 LttvAttributeValue value;
202 guint i;
203
204 g_assert(attribute =
205 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
206 LTTV_TRACES)));
207
208 for(i=0;i<lttvwindowtraces_get_number();i++) {
209 LttvTrace *trace_v = lttvwindowtraces_get_trace(i);
210
211 g_assert(trace_v != NULL);
212
213 if(trace_v == trace) {
214 /* Found */
8bc02ec8 215 LttvAttribute *l_attribute;
216
217 /* create new traceset and tracesetcontext */
218 LttvTraceset *ts;
219 LttvTracesetContext *tsc;
220
221 l_attribute = lttv_trace_attribute(trace);
222
223
224 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
225 LTTV_REQUESTS_QUEUE);
226
227 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
228 LTTV_REQUESTS_CURRENT);
229
230 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
231 LTTV_NOTIFY_QUEUE);
232
233 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
234 LTTV_NOTIFY_CURRENT);
235
236 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(l_attribute),
237 LTTV_COMPUTATION_TRACESET,
238 LTTV_POINTER,
239 &value));
240 ts = (LttvTraceset*)*(value.v_pointer);
241
242 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(l_attribute),
243 LTTV_COMPUTATION_TRACESET_CONTEXT,
244 LTTV_POINTER,
245 &value));
246 tsc = (LttvTracesetContext*)*(value.v_pointer);
247
248 lttv_context_fini(tsc);
249 g_object_unref(tsc);
250 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
251 LTTV_COMPUTATION_TRACESET_CONTEXT);
252 lttv_traceset_destroy(ts);
253 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
254 LTTV_COMPUTATION_TRACESET);
255
256 /* finally, remove the global attribute */
a1a2b649 257 lttv_attribute_remove(attribute, i);
8bc02ec8 258
a1a2b649 259 return;
260 }
261 }
262}
263
264
265/**
266 * Function to request data from a specific trace
267 *
268 * The memory allocated for the request will be managed by the API.
269 *
270 * @param trace the trace to compute
271 * @param module_name the name of the module which registered global computation
272 * hooks.
273 */
274
275void lttvwindowtraces_background_request_queue
276 (LttvTrace *trace, gchar *module_name)
277{
278 BackgroundRequest *bg_req;
279 LttvAttribute *attribute = lttv_trace_attribute(trace);
280 LttvAttributeValue value;
281 GSList **slist;
282 guint num;
283
284 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
285 LTTV_REQUESTS_QUEUE,
286 LTTV_POINTER,
287 &value));
288 slist = (GSList**)(value.v_pointer);
289
290 bg_req = g_new(BackgroundRequest,1);
291 bg_req->module_name = g_quark_from_string(module_name);
292 bg_req->trace = trace;
293
294 *slist = g_slist_append(*slist, bg_req);
295}
296
297/**
298 * Remove a background request from a trace.
299 *
300 * This should ONLY be used by the modules which registered the global hooks
301 * (module_name). If this is called by the viewers, it may lead to incomplete
302 * and incoherent background processing information.
303 *
304 * Even if the module which deals with the hooks removes the background
305 * requests, it may cause a problem if the module gets loaded again in the
306 * session : the data will be partially calculated. The calculation function
307 * must deal with this case correctly.
308 *
309 * @param trace the trace to compute
310 * @param module_name the name of the module which registered global computation
311 * hooks.
312 */
313
314void lttvwindowtraces_background_request_remove
315 (LttvTrace *trace, gchar *module_name)
316{
317 LttvAttribute *attribute = lttv_trace_attribute(trace);
318 LttvAttributeValue value;
319 GSList *iter = NULL;
320 GSList **slist;
321
322 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
323 LTTV_REQUESTS_QUEUE,
324 LTTV_POINTER,
325 &value));
326 slist = (GSList**)(value.v_pointer);
327
328 for(iter=*slist;iter!=NULL;) {
329 BackgroundRequest *bg_req =
330 (BackgroundRequest *)iter->data;
331
332 if(bg_req->module_name == g_quark_from_string(module_name)) {
333 GSList *rem_iter = iter;
334 iter=g_slist_next(iter);
335 g_free(bg_req);
336 *slist = g_slist_delete_link(*slist, rem_iter);
337 } else {
338 iter=g_slist_next(iter);
339 }
340 }
341}
342
343
344/**
345 * Register a callback to be called when requested data is passed in the next
346 * queued background processing.
347 *
348 * @param owner owner of the background notification
349 * @param trace the trace computed
350 * @param notify_time time when notification hooks must be called
351 * @param notify_position position when notification hooks must be called
352 * @param notify Hook to call when the notify position is passed
353 */
354
355void lttvwindowtraces_background_notify_queue
356 (gpointer owner,
357 LttvTrace *trace,
358 LttTime notify_time,
359 const LttvTracesetContextPosition *notify_position,
360 const LttvHooks *notify)
361{
362 BackgroundNotify *bg_notify;
363 LttvAttribute *attribute = lttv_trace_attribute(trace);
364 LttvAttributeValue value;
365 GSList **slist;
366
367 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
368 LTTV_NOTIFY_QUEUE,
369 LTTV_POINTER,
370 &value));
371 slist = (GSList**)(value.v_pointer);
372
373
374 bg_notify = g_new(BackgroundNotify,1);
375
376 bg_notify->owner = owner;
377 bg_notify->trace = trace;
378 bg_notify->notify_time = notify_time;
379 bg_notify->notify_position = ltt_traceset_context_position_new();
380 lttv_traceset_context_position_copy(bg_notify->notify_position,
381 notify_position);
382 bg_notify->notify = lttv_hooks_new();
383 lttv_hooks_add_list(bg_notify->notify, notify);
384
385 *slist = g_slist_append(*slist, bg_notify);
386}
387
388/**
389 * Register a callback to be called when requested data is passed in the current
390 * background processing.
391 *
392 * @param owner owner of the background notification
393 * @param trace the trace computed
394 * @param notify_time time when notification hooks must be called
395 * @param notify_position position when notification hooks must be called
396 * @param notify Hook to call when the notify position is passed
397 */
398
399void lttvwindowtraces_background_notify_current
400 (gpointer owner,
401 LttvTrace *trace,
402 LttTime notify_time,
403 const LttvTracesetContextPosition *notify_position,
404 const LttvHooks *notify)
405{
406 BackgroundNotify *bg_notify;
407 LttvAttribute *attribute = lttv_trace_attribute(trace);
408 LttvAttributeValue value;
409 GSList **slist;
410
411 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
412 LTTV_NOTIFY_CURRENT,
413 LTTV_POINTER,
414 &value));
415 slist = (GSList**)(value.v_pointer);
416
417 bg_notify = g_new(BackgroundNotify,1);
418
419 bg_notify->owner = owner;
420 bg_notify->trace = trace;
421 bg_notify->notify_time = notify_time;
422 bg_notify->notify_position = ltt_traceset_context_position_new();
423 lttv_traceset_context_position_copy(bg_notify->notify_position,
424 notify_position);
425 bg_notify->notify = lttv_hooks_new();
426 lttv_hooks_add_list(bg_notify->notify, notify);
427
428 *slist = g_slist_append(*slist, bg_notify);
429}
430
431/**
432 * Removes all the notifications requests from a specific viewer.
433 *
434 * @param owner owner of the background notification
435 */
436
437void lttvwindowtraces_background_notify_remove(gpointer owner)
438{
439 guint i;
440
441 for(i=0;i<lttvwindowtraces_get_number();i++) {
442 LttvAttribute *attribute;
443 LttvAttributeValue value;
444 LttvTrace *trace_v = lttvwindowtraces_get_trace(i);
445 GSList **slist;
446 GSList *iter = NULL;
447
448 g_assert(trace_v != NULL);
449
450 LttvAttribute *t_a = lttv_trace_attribute(trace_v);
451
452 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
453 LTTV_NOTIFY_QUEUE,
454 LTTV_POINTER,
455 &value));
456 slist = (GSList**)(value.v_pointer);
457
458 for(iter=*slist;iter!=NULL;) {
459
460 BackgroundNotify *bg_notify = (BackgroundNotify*)iter->data;
461
462 if(bg_notify->owner == owner) {
463 GSList *rem_iter = iter;
464 iter=g_slist_next(iter);
465 lttv_traceset_context_position_destroy(
466 bg_notify->notify_position);
467 lttv_hooks_destroy(bg_notify->notify);
468 g_free(bg_notify);
469 g_slist_remove_link(*slist, rem_iter);
470 } else {
471 iter=g_slist_next(iter);
472 }
473 }
474
475 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
476 LTTV_NOTIFY_CURRENT,
477 LTTV_POINTER,
478 &value));
479 slist = (GSList**)(value.v_pointer);
480
481 for(iter=*slist;iter!=NULL;) {
482
483 BackgroundNotify *bg_notify = (BackgroundNotify*)iter->data;
484
485 if(bg_notify->owner == owner) {
486 GSList *rem_iter = iter;
487 iter=g_slist_next(iter);
488 lttv_traceset_context_position_destroy(
489 bg_notify->notify_position);
490 lttv_hooks_destroy(bg_notify->notify);
491 g_free(bg_notify);
492 g_slist_remove_link(*slist, rem_iter);
493 } else {
494 iter=g_slist_next(iter);
495 }
496 }
497 }
498}
499
8bc02ec8 500
501/* Background processing helper functions */
502
503void lttvwindowtraces_add_computation_hooks(LttvAttributeName module_name,
504 LttvTracesetContext *tsc)
505{
506 LttvAttribute *g_attribute = lttv_global_attributes();
507 LttvAttribute *module_attribute;
508 LttvAttributeType type;
509 LttvAttributeValue value;
510 LttvHooks *before_chunk_traceset=NULL;
511 LttvHooks *before_chunk_trace=NULL;
512 LttvHooks *before_chunk_tracefile=NULL;
513 LttvHooks *event_hook=NULL;
514 LttvHooksById *event_hook_by_id=NULL;
515
516
517 g_assert(module_attribute =
518 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
519 LTTV_COMPUTATION)));
520
521 g_assert(module_attribute =
522 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
523 LTTV_IATTRIBUTE(module_attribute),
524 module_name)));
525
526 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
527 LTTV_BEFORE_CHUNK_TRACESET,
528 &value);
529 if(type == LTTV_POINTER) {
530 before_chunk_traceset = (LttvHooks*)*(value.v_pointer);
531 }
532
533 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
534 LTTV_BEFORE_CHUNK_TRACE,
535 &value);
536 if(type == LTTV_POINTER) {
537 before_chunk_trace = (LttvHooks*)*(value.v_pointer);
538 }
539
540 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
541 LTTV_BEFORE_CHUNK_TRACEFILE,
542 &value);
543 if(type == LTTV_POINTER) {
544 before_chunk_tracefile = (LttvHooks*)*(value.v_pointer);
545 }
546
547 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
548 LTTV_EVENT_HOOK,
549 &value);
550 if(type == LTTV_POINTER) {
551 event_hook = (LttvHooks*)*(value.v_pointer);
552 }
553
554 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
555 LTTV_EVENT_HOOK_BY_ID,
556 &value);
557 if(type == LTTV_POINTER) {
558 event_hook_by_id = (LttvHooksById*)*(value.v_pointer);
559 }
560
561
562 lttv_process_traceset_begin(tsc,
563 before_chunk_traceset,
564 before_chunk_trace,
565 before_chunk_tracefile,
566 event_hook,
567 event_hook_by_id);
568
569}
570
571void lttvwindowtraces_remove_computation_hooks(LttvAttributeName module_name,
572 LttvTracesetContext *tsc)
573{
574 LttvAttribute *g_attribute = lttv_global_attributes();
575 LttvAttribute *module_attribute;
576 LttvAttributeType type;
577 LttvAttributeValue value;
578 LttvHooks *after_chunk_traceset=NULL;
579 LttvHooks *after_chunk_trace=NULL;
580 LttvHooks *after_chunk_tracefile=NULL;
581 LttvHooks *event_hook=NULL;
582 LttvHooksById *event_hook_by_id=NULL;
583
584
585 g_assert(module_attribute =
586 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
587 LTTV_COMPUTATION)));
588
589 g_assert(module_attribute =
590 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
591 LTTV_IATTRIBUTE(module_attribute),
592 module_name)));
593
594 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
595 LTTV_AFTER_CHUNK_TRACESET,
596 &value);
597 if(type == LTTV_POINTER) {
598 after_chunk_traceset = (LttvHooks*)*(value.v_pointer);
599 }
600
601 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
602 LTTV_AFTER_CHUNK_TRACE,
603 &value);
604 if(type == LTTV_POINTER) {
605 after_chunk_trace = (LttvHooks*)*(value.v_pointer);
606 }
607
608 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
609 LTTV_AFTER_CHUNK_TRACEFILE,
610 &value);
611 if(type == LTTV_POINTER) {
612 after_chunk_tracefile = (LttvHooks*)*(value.v_pointer);
613 }
614
615 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
616 LTTV_EVENT_HOOK,
617 &value);
618 if(type == LTTV_POINTER) {
619 event_hook = (LttvHooks*)*(value.v_pointer);
620 }
621
622 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
623 LTTV_EVENT_HOOK_BY_ID,
624 &value);
625 if(type == LTTV_POINTER) {
626 event_hook_by_id = (LttvHooksById*)*(value.v_pointer);
627 }
628
629
630 lttv_process_traceset_end(tsc,
631 after_chunk_traceset,
632 after_chunk_trace,
633 after_chunk_tracefile,
634 event_hook,
635 event_hook_by_id);
636}
637
638
639void lttvwindowtraces_set_in_progress(LttvAttributeName module_name,
640 LttvTrace *trace)
641{
642 LttvAttribute *attribute = lttv_trace_attribute(trace);
643 LttvAttributeValue value;
644
645 g_assert(attribute =
646 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
647 module_name)));
648
649 value = lttv_iattribute_add(LTTV_IATTRIBUTE(attribute),
650 LTTV_IN_PROGRESS,
651 LTTV_INT);
652 /* the value is left unset. The only presence of the attribute is necessary.
653 */
654}
655
656void lttvwindowtraces_unset_in_progress(LttvAttributeName module_name,
657 LttvTrace *trace)
658{
659 LttvAttribute *attribute = lttv_trace_attribute(trace);
660
661 g_assert(attribute =
662 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
663 module_name)));
664
665 lttv_iattribute_remove(LTTV_IATTRIBUTE(attribute),
666 LTTV_IN_PROGRESS);
667}
668
669gboolean lttvwindowtraces_get_in_progress(LttvAttributeName module_name,
670 LttvTrace *trace)
671{
672 LttvAttribute *attribute = lttv_trace_attribute(trace);
673 LttvAttributeType type;
674 LttvAttributeValue value;
675
676 g_assert(attribute =
677 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
678 module_name)));
679
680 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
681 LTTV_IN_PROGRESS,
682 &value);
683 /* The only presence of the attribute is necessary. */
684 if(type == LTTV_NONE)
685 return FALSE;
686 else
687 return TRUE;
688}
689
690void lttvwindowtraces_set_ready(LttvAttributeName module_name,
691 LttvTrace *trace)
692{
693 LttvAttribute *attribute = lttv_trace_attribute(trace);
694 LttvAttributeValue value;
695
696 g_assert(attribute =
697 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
698 module_name)));
699
700 value = lttv_iattribute_add(LTTV_IATTRIBUTE(attribute),
701 LTTV_READY,
702 LTTV_INT);
703 /* the value is left unset. The only presence of the attribute is necessary.
704 */
705}
706
707void lttvwindowtraces_unset_ready(LttvAttributeName module_name,
708 LttvTrace *trace)
709{
710 LttvAttribute *attribute = lttv_trace_attribute(trace);
711
712 g_assert(attribute =
713 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
714 module_name)));
715
716 lttv_iattribute_remove(LTTV_IATTRIBUTE(attribute),
717 LTTV_READY);
718}
719
720gboolean lttvwindowtraces_get_ready(LttvAttributeName module_name,
721 LttvTrace *trace)
722{
723 LttvAttribute *attribute = lttv_trace_attribute(trace);
724 LttvAttributeType type;
725 LttvAttributeValue value;
726
727 g_assert(attribute =
728 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
729 module_name)));
730
731 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
732 LTTV_READY,
733 &value);
734 /* The only presence of the attribute is necessary. */
735 if(type == LTTV_NONE)
736 return FALSE;
737 else
738 return TRUE;
739}
740
741
742
743/* lttvwindowtraces_process_pending_requests
744 *
745 * This internal function gets called by g_idle, taking care of the pending
746 * requests.
747 *
748 */
749
750
751gboolean lttvwindowtraces_process_pending_requests(LttvTrace *trace)
752{
753 LttvTracesetContext *tsc;
754 LttvTraceset *ts;
755 LttvAttribute *attribute;
756 GSList *list_out, *list_in, *notify_in, *notify_out;
757 LttvAttributeValue value;
758 LttvAttributeType type;
759
760 if(trace == NULL)
761 return FALSE;
762
763 attribute = lttv_trace_attribute(trace);
764
765 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
766 LTTV_REQUESTS_QUEUE,
767 &value);
768 g_assert(type == LTTV_POINTER);
769 list_out = (GSList*)*(value.v_pointer);
770
771 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
772 LTTV_REQUESTS_CURRENT,
773 &value);
774 g_assert(type == LTTV_POINTER);
775 list_in = (GSList*)*(value.v_pointer);
776
777 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
778 LTTV_NOTIFY_QUEUE,
779 &value);
780 g_assert(type == LTTV_POINTER);
781 notify_out = (GSList*)*(value.v_pointer);
782
783 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
784 LTTV_NOTIFY_CURRENT,
785 &value);
786 g_assert(type == LTTV_POINTER);
787 notify_in = (GSList*)*(value.v_pointer);
788
789 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
790 LTTV_COMPUTATION_TRACESET,
791 &value);
792 g_assert(type == LTTV_POINTER);
793 ts = (LttvTraceset*)*(value.v_pointer);
794
795 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
796 LTTV_COMPUTATION_TRACESET_CONTEXT,
797 &value);
798 g_assert(type == LTTV_POINTER);
799 tsc = (LttvTracesetContext*)*(value.v_pointer);
800 g_assert(LTTV_IS_TRACESET_CONTEXT(tsc));
801
802 /* There is no events requests pending : we should never have been called! */
803 g_assert(g_slist_length(list_out) != 0 || g_slist_length(list_in) != 0);
804
805
806
807 /* 1. Before processing */
808 {
809 /* if list_in is empty */
810 if(g_slist_length(list_in) == 0) {
811
812 {
813 /* - Add all requests in list_out to list_in, empty list_out */
814 GSList *iter = list_out;
815
816 while(iter != NULL) {
817 gboolean remove = FALSE;
818 gboolean free_data = FALSE;
819
820 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
821
822 remove = TRUE;
823 free_data = FALSE;
824 list_in = g_slist_append(list_in, bg_req);
825
826 /* Go to next */
827 if(remove)
828 {
829 GSList *remove_iter = iter;
830
831 iter = g_slist_next(iter);
832 if(free_data) g_free(remove_iter->data);
833 list_out = g_slist_remove_link(list_out, remove_iter);
834 } else { // not remove
835 iter = g_slist_next(iter);
836 }
837 }
838 }
839
840 {
841 GSList *iter = list_in;
842 /* - for each request in list_in */
843 while(iter != NULL) {
844
845 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
846 /*- add hooks to context*/
847 lttvwindowtraces_set_in_progress(bg_req->module_name,
848 bg_req->trace);
849
850 iter = g_slist_next(iter);
851 }
852 }
853
854 /* - seek trace to start */
855 {
856 LttTime start = { 0, 0};
857 lttv_process_traceset_seek_time(tsc, start);
858 }
859
860 /* - Move all notifications from notify_out to notify_in. */
861 {
862 GSList *iter = notify_out;
863 g_assert(g_slist_length(notify_in) == 0);
864
865 while(iter != NULL) {
866 gboolean remove = FALSE;
867 gboolean free_data = FALSE;
868
869 BackgroundNotify *notify_req = (BackgroundNotify*)iter->data;
870
871 remove = TRUE;
872 free_data = FALSE;
873 notify_in = g_slist_append(notify_in, notify_req);
874
875 /* Go to next */
876 if(remove)
877 {
878 GSList *remove_iter = iter;
879
880 iter = g_slist_next(iter);
881 if(free_data) g_free(remove_iter->data);
882 notify_out = g_slist_remove_link(notify_out, remove_iter);
883 } else { // not remove
884 iter = g_slist_next(iter);
885 }
886 }
887 }
888 }
889
890 {
891 GSList *iter = list_in;
892 /* - for each request in list_in */
893 while(iter != NULL) {
894
895 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
896 /*- Call before chunk hooks for list_in*/
897 /*- add hooks to context*/
898 lttvwindowtraces_add_computation_hooks(bg_req->module_name,
899 tsc);
900 iter = g_slist_next(iter);
901 }
902 }
903 }
904
905 /* 2. call process traceset middle for a chunk */
906 {
907 /*(assert list_in is not empty! : should not even be called in that case)*/
908 LttTime end = { G_MAXUINT, G_MAXUINT };
909 g_assert(g_slist_length(list_in) != 0);
910
911 lttv_process_traceset_middle(tsc, end, CHUNK_NUM_EVENTS, NULL);
912 }
913
914 /* 3. After the chunk */
915 {
916 /* 3.1 call after_chunk hooks for list_in */
917 {
918 GSList *iter = list_in;
919 /* - for each request in list_in */
920 while(iter != NULL) {
921
922 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
923 /* - Call after chunk hooks for list_in */
924 /* - remove hooks from context */
925 lttvwindowtraces_remove_computation_hooks(bg_req->module_name,
926 tsc);
927 iter = g_slist_next(iter);
928 }
929 }
930
931 /* 3.2 for each notify_in */
932 {
933 GSList *iter = notify_in;
934 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
935
936 while(iter != NULL) {
937 gboolean remove = FALSE;
938 gboolean free_data = FALSE;
939
940 BackgroundNotify *notify_req = (BackgroundNotify*)iter->data;
941
942 /* - if current time >= notify time, call notify and remove from
943 * notify_in.
944 * - if current position >= notify position, call notify and remove
945 * from notify_in.
946 */
947 if( (tfc != NULL &&
948 ltt_time_compare(notify_req->notify_time, tfc->timestamp) >= 0)
949 ||
950 (lttv_traceset_context_ctx_pos_compare(tsc,
951 notify_req->notify_position) >= 0)
952 ) {
953
954 lttv_hooks_call(notify_req->notify, notify_req);
955
956 remove = TRUE;
957 free_data = TRUE;
958 }
959
960 /* Go to next */
961 if(remove)
962 {
963 GSList *remove_iter = iter;
964
965 iter = g_slist_next(iter);
966 if(free_data) g_free(remove_iter->data);
967 notify_in = g_slist_remove_link(notify_in, remove_iter);
968 } else { // not remove
969 iter = g_slist_next(iter);
970 }
971 }
972 }
973
974 {
975 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
976 /* 3.3 if end of trace reached */
977 if(tfc == NULL || ltt_time_compare(tfc->timestamp,
978 tsc->time_span.end_time) > 0) {
979
980 /* - for each request in list_in */
981 {
982 GSList *iter = list_in;
983
984 while(iter != NULL) {
985 gboolean remove = FALSE;
986 gboolean free_data = FALSE;
987
988 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
989
990 /* - set hooks'in_progress flag to FALSE */
991 lttvwindowtraces_unset_in_progress(bg_req->module_name,
992 bg_req->trace);
993 /* - set hooks'ready flag to TRUE */
994 lttvwindowtraces_set_ready(bg_req->module_name,
995 bg_req->trace);
996 /* - remove request */
997 remove = TRUE;
998 free_data = TRUE;
999
1000 /* Go to next */
1001 if(remove)
1002 {
1003 GSList *remove_iter = iter;
1004
1005 iter = g_slist_next(iter);
1006 if(free_data) g_free(remove_iter->data);
1007 list_in = g_slist_remove_link(list_in, remove_iter);
1008 } else { // not remove
1009 iter = g_slist_next(iter);
1010 }
1011 }
1012 }
1013
1014 /* - for each notifications in notify_in */
1015 {
1016 GSList *iter = notify_in;
1017
1018 while(iter != NULL) {
1019 gboolean remove = FALSE;
1020 gboolean free_data = FALSE;
1021
1022 BackgroundNotify *notify_req = (BackgroundNotify*)iter->data;
1023
1024 /* - call notify and remove from notify_in */
1025 lttv_hooks_call(notify_req->notify, notify_req);
1026 remove = TRUE;
1027 free_data = TRUE;
1028
1029 /* Go to next */
1030 if(remove)
1031 {
1032 GSList *remove_iter = iter;
1033
1034 iter = g_slist_next(iter);
1035 if(free_data) g_free(remove_iter->data);
1036 notify_in = g_slist_remove_link(notify_in, remove_iter);
1037 } else { // not remove
1038 iter = g_slist_next(iter);
1039 }
1040 }
1041 }
1042
1043 /* - return FALSE (scheduler stopped) */
1044 return FALSE;
1045 } else {
1046 /* 3.4 else, end of trace not reached */
1047 /* - return TRUE (scheduler still registered) */
1048 return TRUE;
1049 }
1050 }
1051 }
1052}
e62a7964 1053
1054
1055
1056/**
1057 * Register the background computation hooks for a specific module. It adds the
1058 * computation hooks to the global attrubutes, under "computation/module name"
1059 *
1060 * @param module_name A GQuark : the name of the module which computes the
1061 * information.
1062 */
1063void lttvwindowtraces_register_computation_hooks(LttvAttributeName module_name,
1064 LttvHooks *before_chunk_traceset,
1065 LttvHooks *before_chunk_trace,
1066 LttvHooks *before_chunk_tracefile,
1067 LttvHooks *after_chunk_traceset,
1068 LttvHooks *after_chunk_trace,
1069 LttvHooks *after_chunk_tracefile,
1070 LttvHooks *before_request,
1071 LttvHooks *after_request,
1072 LttvHooks *event_hook,
1073 LttvHooksById *event_hook_by_id)
1074{
1075 LttvAttribute *g_attribute = lttv_global_attributes();
1076 LttvAttribute *attribute;
1077 LttvAttributeValue value;
1078
1079 g_assert(attribute =
1080 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
1081 LTTV_COMPUTATION)));
1082
1083 g_assert(attribute =
1084 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
1085 module_name)));
1086
1087 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1088 LTTV_BEFORE_CHUNK_TRACESET,
1089 LTTV_POINTER,
1090 &value));
1091 *(value.v_pointer) = before_chunk_traceset;
1092
1093 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1094 LTTV_BEFORE_CHUNK_TRACE,
1095 LTTV_POINTER,
1096 &value));
1097 *(value.v_pointer) = before_chunk_trace;
1098
1099 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1100 LTTV_BEFORE_CHUNK_TRACEFILE,
1101 LTTV_POINTER,
1102 &value));
1103 *(value.v_pointer) = before_chunk_tracefile;
1104
1105 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1106 LTTV_AFTER_CHUNK_TRACESET,
1107 LTTV_POINTER,
1108 &value));
1109 *(value.v_pointer) = after_chunk_traceset;
1110
1111 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1112 LTTV_AFTER_CHUNK_TRACE,
1113 LTTV_POINTER,
1114 &value));
1115 *(value.v_pointer) = after_chunk_trace;
1116
1117 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1118 LTTV_AFTER_CHUNK_TRACEFILE,
1119 LTTV_POINTER,
1120 &value));
1121 *(value.v_pointer) = after_chunk_tracefile;
1122
1123 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1124 LTTV_BEFORE_REQUEST,
1125 LTTV_POINTER,
1126 &value));
1127 *(value.v_pointer) = before_request;
1128
1129 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1130 LTTV_AFTER_REQUEST,
1131 LTTV_POINTER,
1132 &value));
1133 *(value.v_pointer) = after_request;
1134
1135 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1136 LTTV_EVENT_HOOK,
1137 LTTV_POINTER,
1138 &value));
1139 *(value.v_pointer) = event_hook;
1140
1141 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1142 LTTV_EVENT_HOOK_BY_ID,
1143 LTTV_POINTER,
1144 &value));
1145 *(value.v_pointer) = event_hook_by_id;
1146
1147}
1148
1149
1150/**
1151 * It removes all the requests than can be currently processed by the
1152 * background computation algorithm for all the traces (list_in and list_out).
1153 *
1154 * Leaves the flag to in_progress or none.. depending if current or queue
1155 *
1156 * @param module_name A GQuark : the name of the module which computes the
1157 * information.
1158 */
1159void lttvwindowtraces_unregister_requests(LttvAttributeName module_name)
1160{
1161 guint i;
1162
1163 for(i=0;i<lttvwindowtraces_get_number();i++) {
1164 LttvTrace *trace_v = lttvwindowtraces_get_trace(i);
1165 g_assert(trace_v != NULL);
1166 LttTrace *trace;
1167 LttvAttribute *attribute = lttv_trace_attribute(trace_v);
1168 LttvAttributeValue value;
1169 GSList *queue, *current;
1170 GSList *iter;
1171
1172 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1173 LTTV_REQUESTS_QUEUE,
1174 LTTV_POINTER,
1175 &value));
1176 queue = (GSList*)*(value.v_pointer);
1177
1178 iter = queue;
1179 while(iter != NULL) {
1180 gboolean remove = FALSE;
1181 gboolean free_data = FALSE;
1182
1183 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
1184
1185 if(bg_req->module_name == module_name) {
1186 remove = TRUE;
1187 free_data = TRUE;
1188 }
1189
1190 /* Go to next */
1191 if(remove)
1192 {
1193 GSList *remove_iter = iter;
1194
1195 iter = g_slist_next(iter);
1196 if(free_data) g_free(remove_iter->data);
1197 queue = g_slist_remove_link(queue, remove_iter);
1198 } else { // not remove
1199 iter = g_slist_next(iter);
1200 }
1201 }
1202
1203
1204 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1205 LTTV_REQUESTS_CURRENT,
1206 LTTV_POINTER,
1207 &value));
1208 current = (GSList*)*(value.v_pointer);
1209
1210 iter = current;
1211 while(iter != NULL) {
1212 gboolean remove = FALSE;
1213 gboolean free_data = FALSE;
1214
1215 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
1216
1217 if(bg_req->module_name == module_name) {
1218 remove = TRUE;
1219 free_data = TRUE;
1220 }
1221
1222 /* Go to next */
1223 if(remove)
1224 {
1225 GSList *remove_iter = iter;
1226
1227 iter = g_slist_next(iter);
1228 if(free_data) g_free(remove_iter->data);
1229 current = g_slist_remove_link(current, remove_iter);
1230 } else { // not remove
1231 iter = g_slist_next(iter);
1232 }
1233 }
1234 }
1235}
1236
1237
1238/**
1239 * Unregister the background computation hooks for a specific module.
1240 *
1241 * It also removes all the requests than can be currently processed by the
1242 * background computation algorithm for all the traces (list_in and list_out).
1243 *
1244 * @param module_name A GQuark : the name of the module which computes the
1245 * information.
1246 */
1247
1248void lttvwindowtraces_unregister_computation_hooks
1249 (LttvAttributeName module_name)
1250{
1251 LttvAttribute *g_attribute = lttv_global_attributes();
1252 LttvAttribute *attribute;
1253
1254 g_assert(attribute =
1255 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
1256 LTTV_COMPUTATION)));
1257 g_assert(attribute =
1258 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
1259 module_name)));
1260
1261
1262 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1263 LTTV_EVENT_HOOK_BY_ID);
1264 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1265 LTTV_EVENT_HOOK);
1266
1267 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1268 LTTV_AFTER_REQUEST);
1269 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1270 LTTV_BEFORE_REQUEST);
1271
1272 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1273 LTTV_AFTER_CHUNK_TRACEFILE);
1274 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1275 LTTV_AFTER_CHUNK_TRACE);
1276 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1277 LTTV_AFTER_CHUNK_TRACESET);
1278
1279 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1280 LTTV_BEFORE_CHUNK_TRACEFILE);
1281 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1282 LTTV_BEFORE_CHUNK_TRACE);
1283 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1284 LTTV_BEFORE_CHUNK_TRACESET);
1285 /* finally, remove module name */
1286 g_assert(attribute =
1287 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
1288 LTTV_COMPUTATION)));
1289 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1290 module_name);
1291
1292}
1293
1294
This page took 0.069182 seconds and 4 git commands to generate.