background processing initial commit
[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;
72
73 g_assert(trace_v != NULL);
74
75 trace = lttv_trace(trace_v);
76 g_assert(trace != NULL);
77 name = ltt_trace_name(trace);
78
79 if(strcmp(name, path) == 0) {
80 /* Found */
81 return trace_v;
82 }
83 }
84
85 return NULL;
86}
87
88/* Get a trace by its number identifier */
89
90LttvTrace *lttvwindowtraces_get_trace(guint num)
91{
92 LttvAttribute *g_attribute = lttv_global_attributes();
93 LttvAttribute *attribute;
94 LttvAttributeType type;
95 LttvAttributeName name;
96 LttvAttributeValue value;
97
98 g_assert(attribute =
99 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
100 LTTV_TRACES)));
101
102 type = lttv_iattribute_get(LTTV_IATTRIBUTE(attribute), num, &name, &value);
103
104 if(type == LTTV_POINTER) {
105 return (LttvTrace *)*(value.v_pointer);
106 }
107
108 return NULL;
109}
110
111/* Total number of traces */
112
113guint lttvwindowtraces_get_number()
114{
115 LttvAttribute *g_attribute = lttv_global_attributes();
116 LttvAttribute *attribute;
117 LttvAttributeValue value;
118
119 g_assert(attribute =
120 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
121 LTTV_TRACES)));
122
123 return ( lttv_iattribute_get_number(LTTV_IATTRIBUTE(attribute)) );
124}
125
126/* Add a trace to the global attributes */
127
128void lttvwindowtraces_add_trace(LttvTrace *trace)
129{
130 LttvAttribute *g_attribute = lttv_global_attributes();
131 LttvAttribute *attribute;
132 LttvAttributeValue value;
133 guint num;
0fdb8bb0 134 struct stat buf;
135 gchar attribute_path[PATH_MAX];
a1a2b649 136
0fdb8bb0 137 if(stat(ltt_trace_name(lttv_trace(trace)), &buf)) {
138 g_warning("lttvwindowtraces_add_trace: Trace %s not found",
139 ltt_trace_name(lttv_trace(trace)));
140 return;
141 }
142 g_assert(
143 snprintf(attribute_path, PATH_MAX, "%lu:%lu", buf.st_dev, buf.st_ino) >= 0);
144
a1a2b649 145 g_assert(attribute =
146 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
147 LTTV_TRACES)));
0fdb8bb0 148
a1a2b649 149 value = lttv_attribute_add(attribute,
0fdb8bb0 150 g_quark_from_string(attribute_path),
a1a2b649 151 LTTV_POINTER);
152
153 *(value.v_pointer) = (gpointer)trace;
8bc02ec8 154
155 /* create new traceset and tracesetcontext */
156 LttvTraceset *ts;
157 LttvTracesetContext *tsc;
158
159 attribute = lttv_trace_attribute(trace);
160 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
161 LTTV_COMPUTATION_TRACESET,
162 LTTV_POINTER,
163 &value));
164 ts = lttv_traceset_new();
165 *(value.v_pointer) = ts;
166
167 lttv_traceset_add(ts,trace);
168
169 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
170 LTTV_COMPUTATION_TRACESET_CONTEXT,
171 LTTV_POINTER,
172 &value));
173 tsc = g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
174 *(value.v_pointer) = tsc;
175
176 lttv_context_init(tsc, ts);
177
178 value = lttv_attribute_add(attribute,
179 LTTV_REQUESTS_QUEUE,
180 LTTV_POINTER);
181
182 value = lttv_attribute_add(attribute,
183 LTTV_REQUESTS_CURRENT,
184 LTTV_POINTER);
185
186 value = lttv_attribute_add(attribute,
187 LTTV_NOTIFY_QUEUE,
188 LTTV_POINTER);
189
190 value = lttv_attribute_add(attribute,
191 LTTV_NOTIFY_CURRENT,
192 LTTV_POINTER);
193
a1a2b649 194}
195
196/* Remove a trace from the global attributes */
197
198void lttvwindowtraces_remove_trace(LttvTrace *trace)
199{
200 LttvAttribute *g_attribute = lttv_global_attributes();
201 LttvAttribute *attribute;
202 LttvAttributeValue value;
203 guint i;
204
205 g_assert(attribute =
206 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
207 LTTV_TRACES)));
208
209 for(i=0;i<lttvwindowtraces_get_number();i++) {
210 LttvTrace *trace_v = lttvwindowtraces_get_trace(i);
211
212 g_assert(trace_v != NULL);
213
214 if(trace_v == trace) {
215 /* Found */
8bc02ec8 216 LttvAttribute *l_attribute;
217
218 /* create new traceset and tracesetcontext */
219 LttvTraceset *ts;
220 LttvTracesetContext *tsc;
221
222 l_attribute = lttv_trace_attribute(trace);
223
224
225 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
226 LTTV_REQUESTS_QUEUE);
227
228 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
229 LTTV_REQUESTS_CURRENT);
230
231 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
232 LTTV_NOTIFY_QUEUE);
233
234 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
235 LTTV_NOTIFY_CURRENT);
236
237 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(l_attribute),
238 LTTV_COMPUTATION_TRACESET,
239 LTTV_POINTER,
240 &value));
241 ts = (LttvTraceset*)*(value.v_pointer);
242
243 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(l_attribute),
244 LTTV_COMPUTATION_TRACESET_CONTEXT,
245 LTTV_POINTER,
246 &value));
247 tsc = (LttvTracesetContext*)*(value.v_pointer);
248
249 lttv_context_fini(tsc);
250 g_object_unref(tsc);
251 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
252 LTTV_COMPUTATION_TRACESET_CONTEXT);
253 lttv_traceset_destroy(ts);
254 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
255 LTTV_COMPUTATION_TRACESET);
256
257 /* finally, remove the global attribute */
a1a2b649 258 lttv_attribute_remove(attribute, i);
8bc02ec8 259
a1a2b649 260 return;
261 }
262 }
263}
264
265
266/**
267 * Function to request data from a specific trace
268 *
269 * The memory allocated for the request will be managed by the API.
270 *
271 * @param trace the trace to compute
272 * @param module_name the name of the module which registered global computation
273 * hooks.
274 */
275
276void lttvwindowtraces_background_request_queue
277 (LttvTrace *trace, gchar *module_name)
278{
279 BackgroundRequest *bg_req;
280 LttvAttribute *attribute = lttv_trace_attribute(trace);
281 LttvAttributeValue value;
282 GSList **slist;
283 guint num;
284
285 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
286 LTTV_REQUESTS_QUEUE,
287 LTTV_POINTER,
288 &value));
289 slist = (GSList**)(value.v_pointer);
290
291 bg_req = g_new(BackgroundRequest,1);
292 bg_req->module_name = g_quark_from_string(module_name);
293 bg_req->trace = trace;
294
295 *slist = g_slist_append(*slist, bg_req);
296}
297
298/**
299 * Remove a background request from a trace.
300 *
301 * This should ONLY be used by the modules which registered the global hooks
302 * (module_name). If this is called by the viewers, it may lead to incomplete
303 * and incoherent background processing information.
304 *
305 * Even if the module which deals with the hooks removes the background
306 * requests, it may cause a problem if the module gets loaded again in the
307 * session : the data will be partially calculated. The calculation function
308 * must deal with this case correctly.
309 *
310 * @param trace the trace to compute
311 * @param module_name the name of the module which registered global computation
312 * hooks.
313 */
314
315void lttvwindowtraces_background_request_remove
316 (LttvTrace *trace, gchar *module_name)
317{
318 LttvAttribute *attribute = lttv_trace_attribute(trace);
319 LttvAttributeValue value;
320 GSList *iter = NULL;
321 GSList **slist;
322
323 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
324 LTTV_REQUESTS_QUEUE,
325 LTTV_POINTER,
326 &value));
327 slist = (GSList**)(value.v_pointer);
328
329 for(iter=*slist;iter!=NULL;) {
330 BackgroundRequest *bg_req =
331 (BackgroundRequest *)iter->data;
332
333 if(bg_req->module_name == g_quark_from_string(module_name)) {
334 GSList *rem_iter = iter;
335 iter=g_slist_next(iter);
336 g_free(bg_req);
337 *slist = g_slist_delete_link(*slist, rem_iter);
338 } else {
339 iter=g_slist_next(iter);
340 }
341 }
342}
343
344
345/**
346 * Register a callback to be called when requested data is passed in the next
347 * queued background processing.
348 *
349 * @param owner owner of the background notification
350 * @param trace the trace computed
351 * @param notify_time time when notification hooks must be called
352 * @param notify_position position when notification hooks must be called
353 * @param notify Hook to call when the notify position is passed
354 */
355
356void lttvwindowtraces_background_notify_queue
357 (gpointer owner,
358 LttvTrace *trace,
359 LttTime notify_time,
360 const LttvTracesetContextPosition *notify_position,
361 const LttvHooks *notify)
362{
363 BackgroundNotify *bg_notify;
364 LttvAttribute *attribute = lttv_trace_attribute(trace);
365 LttvAttributeValue value;
366 GSList **slist;
367
368 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
369 LTTV_NOTIFY_QUEUE,
370 LTTV_POINTER,
371 &value));
372 slist = (GSList**)(value.v_pointer);
373
374
375 bg_notify = g_new(BackgroundNotify,1);
376
377 bg_notify->owner = owner;
378 bg_notify->trace = trace;
379 bg_notify->notify_time = notify_time;
380 bg_notify->notify_position = ltt_traceset_context_position_new();
381 lttv_traceset_context_position_copy(bg_notify->notify_position,
382 notify_position);
383 bg_notify->notify = lttv_hooks_new();
384 lttv_hooks_add_list(bg_notify->notify, notify);
385
386 *slist = g_slist_append(*slist, bg_notify);
387}
388
389/**
390 * Register a callback to be called when requested data is passed in the current
391 * background processing.
392 *
393 * @param owner owner of the background notification
394 * @param trace the trace computed
395 * @param notify_time time when notification hooks must be called
396 * @param notify_position position when notification hooks must be called
397 * @param notify Hook to call when the notify position is passed
398 */
399
400void lttvwindowtraces_background_notify_current
401 (gpointer owner,
402 LttvTrace *trace,
403 LttTime notify_time,
404 const LttvTracesetContextPosition *notify_position,
405 const LttvHooks *notify)
406{
407 BackgroundNotify *bg_notify;
408 LttvAttribute *attribute = lttv_trace_attribute(trace);
409 LttvAttributeValue value;
410 GSList **slist;
411
412 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
413 LTTV_NOTIFY_CURRENT,
414 LTTV_POINTER,
415 &value));
416 slist = (GSList**)(value.v_pointer);
417
418 bg_notify = g_new(BackgroundNotify,1);
419
420 bg_notify->owner = owner;
421 bg_notify->trace = trace;
422 bg_notify->notify_time = notify_time;
423 bg_notify->notify_position = ltt_traceset_context_position_new();
424 lttv_traceset_context_position_copy(bg_notify->notify_position,
425 notify_position);
426 bg_notify->notify = lttv_hooks_new();
427 lttv_hooks_add_list(bg_notify->notify, notify);
428
429 *slist = g_slist_append(*slist, bg_notify);
430}
431
432/**
433 * Removes all the notifications requests from a specific viewer.
434 *
435 * @param owner owner of the background notification
436 */
437
438void lttvwindowtraces_background_notify_remove(gpointer owner)
439{
440 guint i;
441
442 for(i=0;i<lttvwindowtraces_get_number();i++) {
443 LttvAttribute *attribute;
444 LttvAttributeValue value;
445 LttvTrace *trace_v = lttvwindowtraces_get_trace(i);
446 GSList **slist;
447 GSList *iter = NULL;
448
449 g_assert(trace_v != NULL);
450
451 LttvAttribute *t_a = lttv_trace_attribute(trace_v);
452
453 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
454 LTTV_NOTIFY_QUEUE,
455 LTTV_POINTER,
456 &value));
457 slist = (GSList**)(value.v_pointer);
458
459 for(iter=*slist;iter!=NULL;) {
460
461 BackgroundNotify *bg_notify = (BackgroundNotify*)iter->data;
462
463 if(bg_notify->owner == owner) {
464 GSList *rem_iter = iter;
465 iter=g_slist_next(iter);
466 lttv_traceset_context_position_destroy(
467 bg_notify->notify_position);
468 lttv_hooks_destroy(bg_notify->notify);
469 g_free(bg_notify);
470 g_slist_remove_link(*slist, rem_iter);
471 } else {
472 iter=g_slist_next(iter);
473 }
474 }
475
476 g_assert(lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
477 LTTV_NOTIFY_CURRENT,
478 LTTV_POINTER,
479 &value));
480 slist = (GSList**)(value.v_pointer);
481
482 for(iter=*slist;iter!=NULL;) {
483
484 BackgroundNotify *bg_notify = (BackgroundNotify*)iter->data;
485
486 if(bg_notify->owner == owner) {
487 GSList *rem_iter = iter;
488 iter=g_slist_next(iter);
489 lttv_traceset_context_position_destroy(
490 bg_notify->notify_position);
491 lttv_hooks_destroy(bg_notify->notify);
492 g_free(bg_notify);
493 g_slist_remove_link(*slist, rem_iter);
494 } else {
495 iter=g_slist_next(iter);
496 }
497 }
498 }
499}
500
8bc02ec8 501
502/* Background processing helper functions */
503
504void lttvwindowtraces_add_computation_hooks(LttvAttributeName module_name,
505 LttvTracesetContext *tsc)
506{
507 LttvAttribute *g_attribute = lttv_global_attributes();
508 LttvAttribute *module_attribute;
509 LttvAttributeType type;
510 LttvAttributeValue value;
511 LttvHooks *before_chunk_traceset=NULL;
512 LttvHooks *before_chunk_trace=NULL;
513 LttvHooks *before_chunk_tracefile=NULL;
514 LttvHooks *event_hook=NULL;
515 LttvHooksById *event_hook_by_id=NULL;
516
517
518 g_assert(module_attribute =
519 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
520 LTTV_COMPUTATION)));
521
522 g_assert(module_attribute =
523 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
524 LTTV_IATTRIBUTE(module_attribute),
525 module_name)));
526
527 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
528 LTTV_BEFORE_CHUNK_TRACESET,
529 &value);
530 if(type == LTTV_POINTER) {
531 before_chunk_traceset = (LttvHooks*)*(value.v_pointer);
532 }
533
534 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
535 LTTV_BEFORE_CHUNK_TRACE,
536 &value);
537 if(type == LTTV_POINTER) {
538 before_chunk_trace = (LttvHooks*)*(value.v_pointer);
539 }
540
541 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
542 LTTV_BEFORE_CHUNK_TRACEFILE,
543 &value);
544 if(type == LTTV_POINTER) {
545 before_chunk_tracefile = (LttvHooks*)*(value.v_pointer);
546 }
547
548 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
549 LTTV_EVENT_HOOK,
550 &value);
551 if(type == LTTV_POINTER) {
552 event_hook = (LttvHooks*)*(value.v_pointer);
553 }
554
555 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
556 LTTV_EVENT_HOOK_BY_ID,
557 &value);
558 if(type == LTTV_POINTER) {
559 event_hook_by_id = (LttvHooksById*)*(value.v_pointer);
560 }
561
562
563 lttv_process_traceset_begin(tsc,
564 before_chunk_traceset,
565 before_chunk_trace,
566 before_chunk_tracefile,
567 event_hook,
568 event_hook_by_id);
569
570}
571
572void lttvwindowtraces_remove_computation_hooks(LttvAttributeName module_name,
573 LttvTracesetContext *tsc)
574{
575 LttvAttribute *g_attribute = lttv_global_attributes();
576 LttvAttribute *module_attribute;
577 LttvAttributeType type;
578 LttvAttributeValue value;
579 LttvHooks *after_chunk_traceset=NULL;
580 LttvHooks *after_chunk_trace=NULL;
581 LttvHooks *after_chunk_tracefile=NULL;
582 LttvHooks *event_hook=NULL;
583 LttvHooksById *event_hook_by_id=NULL;
584
585
586 g_assert(module_attribute =
587 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
588 LTTV_COMPUTATION)));
589
590 g_assert(module_attribute =
591 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
592 LTTV_IATTRIBUTE(module_attribute),
593 module_name)));
594
595 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
596 LTTV_AFTER_CHUNK_TRACESET,
597 &value);
598 if(type == LTTV_POINTER) {
599 after_chunk_traceset = (LttvHooks*)*(value.v_pointer);
600 }
601
602 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
603 LTTV_AFTER_CHUNK_TRACE,
604 &value);
605 if(type == LTTV_POINTER) {
606 after_chunk_trace = (LttvHooks*)*(value.v_pointer);
607 }
608
609 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
610 LTTV_AFTER_CHUNK_TRACEFILE,
611 &value);
612 if(type == LTTV_POINTER) {
613 after_chunk_tracefile = (LttvHooks*)*(value.v_pointer);
614 }
615
616 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
617 LTTV_EVENT_HOOK,
618 &value);
619 if(type == LTTV_POINTER) {
620 event_hook = (LttvHooks*)*(value.v_pointer);
621 }
622
623 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
624 LTTV_EVENT_HOOK_BY_ID,
625 &value);
626 if(type == LTTV_POINTER) {
627 event_hook_by_id = (LttvHooksById*)*(value.v_pointer);
628 }
629
630
631 lttv_process_traceset_end(tsc,
632 after_chunk_traceset,
633 after_chunk_trace,
634 after_chunk_tracefile,
635 event_hook,
636 event_hook_by_id);
637}
638
639
640void lttvwindowtraces_set_in_progress(LttvAttributeName module_name,
641 LttvTrace *trace)
642{
643 LttvAttribute *attribute = lttv_trace_attribute(trace);
644 LttvAttributeValue value;
645
646 g_assert(attribute =
647 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
648 module_name)));
649
650 value = lttv_iattribute_add(LTTV_IATTRIBUTE(attribute),
651 LTTV_IN_PROGRESS,
652 LTTV_INT);
653 /* the value is left unset. The only presence of the attribute is necessary.
654 */
655}
656
657void lttvwindowtraces_unset_in_progress(LttvAttributeName module_name,
658 LttvTrace *trace)
659{
660 LttvAttribute *attribute = lttv_trace_attribute(trace);
661
662 g_assert(attribute =
663 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
664 module_name)));
665
666 lttv_iattribute_remove(LTTV_IATTRIBUTE(attribute),
667 LTTV_IN_PROGRESS);
668}
669
670gboolean lttvwindowtraces_get_in_progress(LttvAttributeName module_name,
671 LttvTrace *trace)
672{
673 LttvAttribute *attribute = lttv_trace_attribute(trace);
674 LttvAttributeType type;
675 LttvAttributeValue value;
676
677 g_assert(attribute =
678 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
679 module_name)));
680
681 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
682 LTTV_IN_PROGRESS,
683 &value);
684 /* The only presence of the attribute is necessary. */
685 if(type == LTTV_NONE)
686 return FALSE;
687 else
688 return TRUE;
689}
690
691void lttvwindowtraces_set_ready(LttvAttributeName module_name,
692 LttvTrace *trace)
693{
694 LttvAttribute *attribute = lttv_trace_attribute(trace);
695 LttvAttributeValue value;
696
697 g_assert(attribute =
698 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
699 module_name)));
700
701 value = lttv_iattribute_add(LTTV_IATTRIBUTE(attribute),
702 LTTV_READY,
703 LTTV_INT);
704 /* the value is left unset. The only presence of the attribute is necessary.
705 */
706}
707
708void lttvwindowtraces_unset_ready(LttvAttributeName module_name,
709 LttvTrace *trace)
710{
711 LttvAttribute *attribute = lttv_trace_attribute(trace);
712
713 g_assert(attribute =
714 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
715 module_name)));
716
717 lttv_iattribute_remove(LTTV_IATTRIBUTE(attribute),
718 LTTV_READY);
719}
720
721gboolean lttvwindowtraces_get_ready(LttvAttributeName module_name,
722 LttvTrace *trace)
723{
724 LttvAttribute *attribute = lttv_trace_attribute(trace);
725 LttvAttributeType type;
726 LttvAttributeValue value;
727
728 g_assert(attribute =
729 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
730 module_name)));
731
732 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
733 LTTV_READY,
734 &value);
735 /* The only presence of the attribute is necessary. */
736 if(type == LTTV_NONE)
737 return FALSE;
738 else
739 return TRUE;
740}
741
742
743
744/* lttvwindowtraces_process_pending_requests
745 *
746 * This internal function gets called by g_idle, taking care of the pending
747 * requests.
748 *
749 */
750
751
752gboolean lttvwindowtraces_process_pending_requests(LttvTrace *trace)
753{
754 LttvTracesetContext *tsc;
755 LttvTraceset *ts;
756 LttvAttribute *attribute;
757 GSList *list_out, *list_in, *notify_in, *notify_out;
758 LttvAttributeValue value;
759 LttvAttributeType type;
760
761 if(trace == NULL)
762 return FALSE;
763
764 attribute = lttv_trace_attribute(trace);
765
766 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
767 LTTV_REQUESTS_QUEUE,
768 &value);
769 g_assert(type == LTTV_POINTER);
770 list_out = (GSList*)*(value.v_pointer);
771
772 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
773 LTTV_REQUESTS_CURRENT,
774 &value);
775 g_assert(type == LTTV_POINTER);
776 list_in = (GSList*)*(value.v_pointer);
777
778 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
779 LTTV_NOTIFY_QUEUE,
780 &value);
781 g_assert(type == LTTV_POINTER);
782 notify_out = (GSList*)*(value.v_pointer);
783
784 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
785 LTTV_NOTIFY_CURRENT,
786 &value);
787 g_assert(type == LTTV_POINTER);
788 notify_in = (GSList*)*(value.v_pointer);
789
790 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
791 LTTV_COMPUTATION_TRACESET,
792 &value);
793 g_assert(type == LTTV_POINTER);
794 ts = (LttvTraceset*)*(value.v_pointer);
795
796 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
797 LTTV_COMPUTATION_TRACESET_CONTEXT,
798 &value);
799 g_assert(type == LTTV_POINTER);
800 tsc = (LttvTracesetContext*)*(value.v_pointer);
801 g_assert(LTTV_IS_TRACESET_CONTEXT(tsc));
802
803 /* There is no events requests pending : we should never have been called! */
804 g_assert(g_slist_length(list_out) != 0 || g_slist_length(list_in) != 0);
805
806
807
808 /* 1. Before processing */
809 {
810 /* if list_in is empty */
811 if(g_slist_length(list_in) == 0) {
812
813 {
814 /* - Add all requests in list_out to list_in, empty list_out */
815 GSList *iter = list_out;
816
817 while(iter != NULL) {
818 gboolean remove = FALSE;
819 gboolean free_data = FALSE;
820
821 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
822
823 remove = TRUE;
824 free_data = FALSE;
825 list_in = g_slist_append(list_in, bg_req);
826
827 /* Go to next */
828 if(remove)
829 {
830 GSList *remove_iter = iter;
831
832 iter = g_slist_next(iter);
833 if(free_data) g_free(remove_iter->data);
834 list_out = g_slist_remove_link(list_out, remove_iter);
835 } else { // not remove
836 iter = g_slist_next(iter);
837 }
838 }
839 }
840
841 {
842 GSList *iter = list_in;
843 /* - for each request in list_in */
844 while(iter != NULL) {
845
846 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
847 /*- add hooks to context*/
848 lttvwindowtraces_set_in_progress(bg_req->module_name,
849 bg_req->trace);
850
851 iter = g_slist_next(iter);
852 }
853 }
854
855 /* - seek trace to start */
856 {
857 LttTime start = { 0, 0};
858 lttv_process_traceset_seek_time(tsc, start);
859 }
860
861 /* - Move all notifications from notify_out to notify_in. */
862 {
863 GSList *iter = notify_out;
864 g_assert(g_slist_length(notify_in) == 0);
865
866 while(iter != NULL) {
867 gboolean remove = FALSE;
868 gboolean free_data = FALSE;
869
870 BackgroundNotify *notify_req = (BackgroundNotify*)iter->data;
871
872 remove = TRUE;
873 free_data = FALSE;
874 notify_in = g_slist_append(notify_in, notify_req);
875
876 /* Go to next */
877 if(remove)
878 {
879 GSList *remove_iter = iter;
880
881 iter = g_slist_next(iter);
882 if(free_data) g_free(remove_iter->data);
883 notify_out = g_slist_remove_link(notify_out, remove_iter);
884 } else { // not remove
885 iter = g_slist_next(iter);
886 }
887 }
888 }
889 }
890
891 {
892 GSList *iter = list_in;
893 /* - for each request in list_in */
894 while(iter != NULL) {
895
896 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
897 /*- Call before chunk hooks for list_in*/
898 /*- add hooks to context*/
899 lttvwindowtraces_add_computation_hooks(bg_req->module_name,
900 tsc);
901 iter = g_slist_next(iter);
902 }
903 }
904 }
905
906 /* 2. call process traceset middle for a chunk */
907 {
908 /*(assert list_in is not empty! : should not even be called in that case)*/
909 LttTime end = { G_MAXUINT, G_MAXUINT };
910 g_assert(g_slist_length(list_in) != 0);
911
912 lttv_process_traceset_middle(tsc, end, CHUNK_NUM_EVENTS, NULL);
913 }
914
915 /* 3. After the chunk */
916 {
917 /* 3.1 call after_chunk hooks for list_in */
918 {
919 GSList *iter = list_in;
920 /* - for each request in list_in */
921 while(iter != NULL) {
922
923 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
924 /* - Call after chunk hooks for list_in */
925 /* - remove hooks from context */
926 lttvwindowtraces_remove_computation_hooks(bg_req->module_name,
927 tsc);
928 iter = g_slist_next(iter);
929 }
930 }
931
932 /* 3.2 for each notify_in */
933 {
934 GSList *iter = notify_in;
935 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
936
937 while(iter != NULL) {
938 gboolean remove = FALSE;
939 gboolean free_data = FALSE;
940
941 BackgroundNotify *notify_req = (BackgroundNotify*)iter->data;
942
943 /* - if current time >= notify time, call notify and remove from
944 * notify_in.
945 * - if current position >= notify position, call notify and remove
946 * from notify_in.
947 */
948 if( (tfc != NULL &&
949 ltt_time_compare(notify_req->notify_time, tfc->timestamp) >= 0)
950 ||
951 (lttv_traceset_context_ctx_pos_compare(tsc,
952 notify_req->notify_position) >= 0)
953 ) {
954
955 lttv_hooks_call(notify_req->notify, notify_req);
956
957 remove = TRUE;
958 free_data = TRUE;
959 }
960
961 /* Go to next */
962 if(remove)
963 {
964 GSList *remove_iter = iter;
965
966 iter = g_slist_next(iter);
967 if(free_data) g_free(remove_iter->data);
968 notify_in = g_slist_remove_link(notify_in, remove_iter);
969 } else { // not remove
970 iter = g_slist_next(iter);
971 }
972 }
973 }
974
975 {
976 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
977 /* 3.3 if end of trace reached */
978 if(tfc == NULL || ltt_time_compare(tfc->timestamp,
979 tsc->time_span.end_time) > 0) {
980
981 /* - for each request in list_in */
982 {
983 GSList *iter = list_in;
984
985 while(iter != NULL) {
986 gboolean remove = FALSE;
987 gboolean free_data = FALSE;
988
989 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
990
991 /* - set hooks'in_progress flag to FALSE */
992 lttvwindowtraces_unset_in_progress(bg_req->module_name,
993 bg_req->trace);
994 /* - set hooks'ready flag to TRUE */
995 lttvwindowtraces_set_ready(bg_req->module_name,
996 bg_req->trace);
997 /* - remove request */
998 remove = TRUE;
999 free_data = TRUE;
1000
1001 /* Go to next */
1002 if(remove)
1003 {
1004 GSList *remove_iter = iter;
1005
1006 iter = g_slist_next(iter);
1007 if(free_data) g_free(remove_iter->data);
1008 list_in = g_slist_remove_link(list_in, remove_iter);
1009 } else { // not remove
1010 iter = g_slist_next(iter);
1011 }
1012 }
1013 }
1014
1015 /* - for each notifications in notify_in */
1016 {
1017 GSList *iter = notify_in;
1018
1019 while(iter != NULL) {
1020 gboolean remove = FALSE;
1021 gboolean free_data = FALSE;
1022
1023 BackgroundNotify *notify_req = (BackgroundNotify*)iter->data;
1024
1025 /* - call notify and remove from notify_in */
1026 lttv_hooks_call(notify_req->notify, notify_req);
1027 remove = TRUE;
1028 free_data = TRUE;
1029
1030 /* Go to next */
1031 if(remove)
1032 {
1033 GSList *remove_iter = iter;
1034
1035 iter = g_slist_next(iter);
1036 if(free_data) g_free(remove_iter->data);
1037 notify_in = g_slist_remove_link(notify_in, remove_iter);
1038 } else { // not remove
1039 iter = g_slist_next(iter);
1040 }
1041 }
1042 }
1043
1044 /* - return FALSE (scheduler stopped) */
1045 return FALSE;
1046 } else {
1047 /* 3.4 else, end of trace not reached */
1048 /* - return TRUE (scheduler still registered) */
1049 return TRUE;
1050 }
1051 }
1052 }
1053}
This page took 0.066198 seconds and 4 git commands to generate.