787c5a70e12b32ee28c55f53a68f21ceb900e125
[lttv.git] / lttv / lttv / modules / gui / lttvwindow / lttvwindow / lttvwindowtraces.c
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
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <inttypes.h>
32
33 #include <ltt/time.h>
34 #include <ltt/trace.h>
35 #include <glib.h>
36 #include <lttv/lttv.h>
37 #include <lttv/traceset.h>
38 #include <lttv/attribute.h>
39 #include <lttv/tracecontext.h>
40 #include <lttvwindow/lttvwindowtraces.h>
41 #include <lttvwindow/lttvwindow.h> // for CHUNK_NUM_EVENTS
42 #include <lttvwindow/mainwindow-private.h> /* for main window structure */
43
44 extern GSList * g_main_window_list;
45
46 typedef struct _BackgroundRequest {
47 LttvAttributeName module_name; /* Hook path in global attributes,
48 where all standard hooks under computation/.
49 i.e. modulename */
50 LttvTrace *trace; /* trace concerned */
51 GtkWidget *dialog; /* Dialog linked with the request, may be NULL */
52 GtkWidget *parent_window; /* Parent window the dialog must be transient for */
53 } BackgroundRequest;
54
55 typedef struct _BackgroundNotify {
56 gpointer owner;
57 LttvTrace *trace; /* trace */
58 LttTime notify_time;
59 LttvTracesetContextPosition *notify_position;
60 LttvHooks *notify; /* Hook to call when the notify is
61 passed, or at the end of trace */
62 } BackgroundNotify;
63
64
65
66 /* Prototypes */
67 gboolean lttvwindowtraces_process_pending_requests(LttvTrace *trace);
68
69 /* Get a trace by its path name.
70 *
71 * @param path path of the trace on the virtual file system.
72 * @return Pointer to trace if found
73 * NULL is returned if the trace is not present
74 */
75
76 __EXPORT LttvTrace *lttvwindowtraces_get_trace_by_name(gchar *path)
77 {
78 guint i;
79
80 for(i=0;i<lttvwindowtraces_get_number();i++) {
81 LttvTrace *trace_v = lttvwindowtraces_get_trace(i);
82 LttTrace *trace;
83 const gchar *name;
84 g_assert(trace_v != NULL);
85
86 trace = lttv_trace(trace_v);
87 g_assert(trace != NULL);
88 name = g_quark_to_string(ltt_trace_name(trace));
89
90 if(strcmp(name, path) == 0) {
91 /* Found */
92 return trace_v;
93 }
94 }
95
96 return NULL;
97 }
98
99 /* Get a trace by its number identifier */
100
101 __EXPORT LttvTrace *lttvwindowtraces_get_trace(guint num)
102 {
103 LttvAttribute *g_attribute = lttv_global_attributes();
104 LttvAttribute *attribute;
105 LttvAttributeType type;
106 LttvAttributeName name;
107 LttvAttributeValue value;
108 gboolean is_named;
109
110 attribute =
111 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
112 LTTV_TRACES));
113 g_assert(attribute);
114
115 type = lttv_iattribute_get(LTTV_IATTRIBUTE(attribute), num, &name, &value,
116 &is_named);
117
118 if(type == LTTV_POINTER) {
119 return (LttvTrace *)*(value.v_pointer);
120 }
121
122 return NULL;
123 }
124
125 /* Total number of traces */
126
127 __EXPORT guint lttvwindowtraces_get_number()
128 {
129 LttvAttribute *g_attribute = lttv_global_attributes();
130 LttvAttribute *attribute;
131
132 attribute =
133 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
134 LTTV_TRACES));
135 g_assert(attribute);
136
137 return ( lttv_iattribute_get_number(LTTV_IATTRIBUTE(attribute)) );
138 }
139
140 /* Add a trace to the global attributes */
141
142 void lttvwindowtraces_add_trace(LttvTrace *trace)
143 {
144 LttvAttribute *g_attribute = lttv_global_attributes();
145 LttvAttribute *attribute;
146 LttvAttributeValue value;
147 struct stat buf;
148 gchar attribute_path[PATH_MAX];
149 int result;
150 gboolean result_b;
151
152 if(stat(g_quark_to_string(ltt_trace_name(lttv_trace(trace))), &buf)) {
153 g_warning("lttvwindowtraces_add_trace: Trace %s not found",
154 g_quark_to_string(ltt_trace_name(lttv_trace(trace))));
155 return;
156 }
157 result = snprintf(attribute_path, PATH_MAX, "%" PRIu64 ":%" PRIu64,
158 buf.st_dev, buf.st_ino);
159 g_assert(result >= 0);
160
161 attribute =
162 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
163 LTTV_TRACES));
164 g_assert(attribute);
165
166 value = lttv_attribute_add(attribute,
167 g_quark_from_string(attribute_path),
168 LTTV_POINTER);
169
170 *(value.v_pointer) = (gpointer)trace;
171
172 /* create new traceset and tracesetcontext */
173 LttvTraceset *ts;
174 LttvTracesetStats *tss;
175 //LttvTracesetContextPosition *sync_position;
176
177 attribute = lttv_trace_attribute(trace);
178 result_b = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
179 LTTV_COMPUTATION_TRACESET,
180 LTTV_POINTER,
181 &value);
182 g_assert(result_b);
183
184 ts = lttv_traceset_new();
185 *(value.v_pointer) = ts;
186
187 lttv_traceset_add(ts,trace);
188
189 result_b = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
190 LTTV_COMPUTATION_TRACESET_CONTEXT,
191 LTTV_POINTER,
192 &value);
193 g_assert(result_b);
194
195 tss = g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
196 *(value.v_pointer) = tss;
197
198 lttv_context_init(LTTV_TRACESET_CONTEXT(tss), ts);
199 #if 0
200 result_b = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
201 LTTV_COMPUTATION_SYNC_POSITION,
202 LTTV_POINTER,
203 &value);
204 g_assert(result_b);
205
206 sync_position = lttv_traceset_context_position_new();
207 *(value.v_pointer) = sync_position;
208 #endif //0
209 value = lttv_attribute_add(attribute,
210 LTTV_REQUESTS_QUEUE,
211 LTTV_POINTER);
212
213 value = lttv_attribute_add(attribute,
214 LTTV_REQUESTS_CURRENT,
215 LTTV_POINTER);
216
217 value = lttv_attribute_add(attribute,
218 LTTV_NOTIFY_QUEUE,
219 LTTV_POINTER);
220
221 value = lttv_attribute_add(attribute,
222 LTTV_NOTIFY_CURRENT,
223 LTTV_POINTER);
224 }
225
226 /* Remove a trace from the global attributes */
227
228 void lttvwindowtraces_remove_trace(LttvTrace *trace)
229 {
230 LttvAttribute *g_attribute = lttv_global_attributes();
231 LttvAttribute *attribute;
232 LttvAttributeValue value;
233 guint i;
234 gboolean result;
235
236 attribute =
237 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
238 LTTV_TRACES));
239 g_assert(attribute);
240
241 for(i=0;i<lttvwindowtraces_get_number();i++) {
242 LttvTrace *trace_v = lttvwindowtraces_get_trace(i);
243
244 g_assert(trace_v != NULL);
245
246 /* Remove and background computation that could be in progress */
247 g_idle_remove_by_data(trace_v);
248
249 if(trace_v == trace) {
250 /* Found */
251 LttvAttribute *l_attribute;
252
253 /* destroy traceset and tracesetcontext */
254 LttvTraceset *ts;
255 LttvTracesetStats *tss;
256 //LttvTracesetContextPosition *sync_position;
257
258 l_attribute = lttv_trace_attribute(trace);
259
260
261 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
262 LTTV_REQUESTS_QUEUE);
263
264 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
265 LTTV_REQUESTS_CURRENT);
266
267 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
268 LTTV_NOTIFY_QUEUE);
269
270 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
271 LTTV_NOTIFY_CURRENT);
272
273 result = lttv_iattribute_find(LTTV_IATTRIBUTE(l_attribute),
274 LTTV_COMPUTATION_TRACESET,
275 LTTV_POINTER,
276 &value);
277 g_assert(result);
278
279 ts = (LttvTraceset*)*(value.v_pointer);
280 #if 0
281 result = lttv_iattribute_find(LTTV_IATTRIBUTE(l_attribute),
282 LTTV_COMPUTATION_SYNC_POSITION,
283 LTTV_POINTER,
284 &value);
285 g_assert(result);
286
287 sync_position = (LttvTracesetContextPosition*)*(value.v_pointer);
288 lttv_traceset_context_position_destroy(sync_position);
289
290 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
291 LTTV_COMPUTATION_SYNC_POSITION);
292
293 #endif //0
294 result = lttv_iattribute_find(LTTV_IATTRIBUTE(l_attribute),
295 LTTV_COMPUTATION_TRACESET_CONTEXT,
296 LTTV_POINTER,
297 &value);
298 g_assert(result);
299
300 tss = (LttvTracesetStats*)*(value.v_pointer);
301
302 lttv_context_fini(LTTV_TRACESET_CONTEXT(tss));
303 g_object_unref(tss);
304 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
305 LTTV_COMPUTATION_TRACESET_CONTEXT);
306 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(l_attribute),
307 LTTV_COMPUTATION_TRACESET);
308 /* Destroy the traceset and the trace also */
309 lttv_traceset_destroy(ts);
310
311 /* finally, remove the global attribute */
312 lttv_attribute_remove(attribute, i);
313
314 return;
315 }
316 }
317 }
318
319 static void destroy_dialog(BackgroundRequest *bg_req)
320 {
321 gtk_widget_destroy(bg_req->dialog);
322 bg_req->dialog = NULL;
323 }
324
325
326 /**
327 * Function to request data from a specific trace
328 *
329 * The memory allocated for the request will be managed by the API.
330 *
331 * @param widget the current Window
332 * @param trace the trace to compute
333 * @param module_name the name of the module which registered global computation
334 * hooks.
335 */
336
337 __EXPORT void lttvwindowtraces_background_request_queue
338 (GtkWidget *widget, LttvTrace *trace, gchar *module_name)
339 {
340 BackgroundRequest *bg_req;
341 LttvAttribute *attribute = lttv_trace_attribute(trace);
342 LttvAttribute *g_attribute = lttv_global_attributes();
343 LttvAttribute *module_attribute;
344 LttvAttributeValue value;
345 LttvAttributeType type;
346 GSList **slist;
347 gboolean result;
348
349 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
350 LTTV_REQUESTS_QUEUE,
351 LTTV_POINTER,
352 &value);
353 g_assert(result);
354
355 slist = (GSList**)(value.v_pointer);
356
357 /* Verify that the calculator is loaded */
358 module_attribute =
359 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
360 LTTV_COMPUTATION));
361 g_assert(module_attribute);
362
363 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
364 g_quark_from_string(module_name),
365 &value);
366 if(type == LTTV_NONE) {
367 g_critical("Missing background calculator %s", module_name);
368 return;
369 }
370
371 bg_req = g_new(BackgroundRequest,1);
372 bg_req->module_name = g_quark_from_string(module_name);
373 bg_req->trace = trace;
374
375 *slist = g_slist_append(*slist, bg_req);
376
377 /* Priority lower than live servicing */
378 g_idle_remove_by_data(trace);
379 g_idle_add_full((G_PRIORITY_HIGH_IDLE + 23),
380 (GSourceFunc)lttvwindowtraces_process_pending_requests,
381 trace,
382 NULL);
383 /* FIXME : show message in status bar, need context and message id */
384 g_info("Background computation for %s started for trace %p", module_name,
385 trace);
386 GtkWidget *dialog =
387 gtk_message_dialog_new(
388 GTK_WINDOW(widget),
389 GTK_DIALOG_DESTROY_WITH_PARENT,
390 GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
391 "Background computation for %s started for trace %s",
392 module_name,
393 g_quark_to_string(ltt_trace_name(lttv_trace(trace))));
394 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(widget));
395 g_signal_connect_swapped (dialog, "response",
396 G_CALLBACK (destroy_dialog),
397 bg_req);
398 bg_req->dialog = dialog;
399 /* the parent window might vanish : only use this pointer for a
400 * comparison with existing windows */
401 bg_req->parent_window = gtk_widget_get_toplevel(widget);
402 gtk_widget_show(dialog);
403 }
404
405 /**
406 * Remove a background request from a trace.
407 *
408 * This should ONLY be used by the modules which registered the global hooks
409 * (module_name). If this is called by the viewers, it may lead to incomplete
410 * and incoherent background processing information.
411 *
412 * Even if the module which deals with the hooks removes the background
413 * requests, it may cause a problem if the module gets loaded again in the
414 * session : the data will be partially calculated. The calculation function
415 * must deal with this case correctly.
416 *
417 * @param trace the trace to compute
418 * @param module_name the name of the module which registered global computation
419 * hooks.
420 */
421
422 void lttvwindowtraces_background_request_remove
423 (LttvTrace *trace, gchar *module_name)
424 {
425 LttvAttribute *attribute = lttv_trace_attribute(trace);
426 LttvAttributeValue value;
427 GSList *iter = NULL;
428 GSList **slist;
429 gboolean result;
430
431 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
432 LTTV_REQUESTS_QUEUE,
433 LTTV_POINTER,
434 &value);
435 g_assert(result);
436
437 slist = (GSList**)(value.v_pointer);
438
439 for(iter=*slist;iter!=NULL;) {
440 BackgroundRequest *bg_req =
441 (BackgroundRequest *)iter->data;
442
443 if(bg_req->module_name == g_quark_from_string(module_name)) {
444 GSList *rem_iter = iter;
445 iter=g_slist_next(iter);
446 g_free(bg_req);
447 *slist = g_slist_delete_link(*slist, rem_iter);
448 } else {
449 iter=g_slist_next(iter);
450 }
451 }
452 }
453
454 /**
455 * Find a background request in a trace
456 *
457 */
458
459 __EXPORT gboolean lttvwindowtraces_background_request_find
460 (LttvTrace *trace, gchar *module_name)
461 {
462 LttvAttribute *attribute = lttv_trace_attribute(trace);
463 LttvAttributeValue value;
464 GSList *iter = NULL;
465 GSList **slist;
466 gboolean result;
467
468 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
469 LTTV_REQUESTS_QUEUE,
470 LTTV_POINTER,
471 &value);
472 g_assert(result);
473
474 slist = (GSList**)(value.v_pointer);
475
476 for(iter=*slist;iter!=NULL;) {
477 BackgroundRequest *bg_req =
478 (BackgroundRequest *)iter->data;
479
480 if(bg_req->module_name == g_quark_from_string(module_name)) {
481 return TRUE;
482 } else {
483 iter=g_slist_next(iter);
484 }
485 }
486 return FALSE;
487 }
488
489 /**
490 * Register a callback to be called when requested data is passed in the next
491 * queued background processing.
492 *
493 * @param owner owner of the background notification
494 * @param trace the trace computed
495 * @param notify_time time when notification hooks must be called
496 * @param notify_position position when notification hooks must be called
497 * @param notify Hook to call when the notify position is passed
498 */
499
500 __EXPORT void lttvwindowtraces_background_notify_queue
501 (gpointer owner,
502 LttvTrace *trace,
503 LttTime notify_time,
504 const LttvTracesetContextPosition *notify_position,
505 const LttvHooks *notify)
506 {
507 BackgroundNotify *bg_notify;
508 LttvAttribute *attribute = lttv_trace_attribute(trace);
509 LttvAttributeValue value;
510 GSList **slist;
511 gboolean result;
512
513 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
514 LTTV_NOTIFY_QUEUE,
515 LTTV_POINTER,
516 &value);
517 g_assert(result);
518
519 slist = (GSList**)(value.v_pointer);
520
521 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
522 LTTV_COMPUTATION_TRACESET_CONTEXT,
523 LTTV_POINTER,
524 &value);
525 g_assert(result);
526
527 LttvTracesetContext *tsc = (LttvTracesetContext*)(value.v_pointer);
528
529 bg_notify = g_new(BackgroundNotify,1);
530
531 bg_notify->owner = owner;
532 bg_notify->trace = trace;
533 bg_notify->notify_time = notify_time;
534 if(notify_position != NULL) {
535 bg_notify->notify_position = lttv_traceset_context_position_new(tsc);
536 lttv_traceset_context_position_copy(bg_notify->notify_position,
537 notify_position);
538 } else {
539 bg_notify->notify_position = NULL;
540 }
541
542 bg_notify->notify = lttv_hooks_new();
543 lttv_hooks_add_list(bg_notify->notify, notify);
544
545 *slist = g_slist_append(*slist, bg_notify);
546 }
547
548 /**
549 * Register a callback to be called when requested data is passed in the current
550 * background processing.
551 *
552 * @param owner owner of the background notification
553 * @param trace the trace computed
554 * @param notify_time time when notification hooks must be called
555 * @param notify_position position when notification hooks must be called
556 * @param notify Hook to call when the notify position is passed
557 */
558
559 __EXPORT void lttvwindowtraces_background_notify_current
560 (gpointer owner,
561 LttvTrace *trace,
562 LttTime notify_time,
563 const LttvTracesetContextPosition *notify_position,
564 const LttvHooks *notify)
565 {
566 BackgroundNotify *bg_notify;
567 LttvAttribute *attribute = lttv_trace_attribute(trace);
568 LttvAttributeValue value;
569 GSList **slist;
570 gboolean result;
571
572 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
573 LTTV_NOTIFY_CURRENT,
574 LTTV_POINTER,
575 &value);
576 g_assert(result);
577
578 slist = (GSList**)(value.v_pointer);
579
580 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
581 LTTV_COMPUTATION_TRACESET_CONTEXT,
582 LTTV_POINTER,
583 &value);
584 g_assert(result);
585
586 LttvTracesetContext *tsc = (LttvTracesetContext*)(value.v_pointer);
587
588
589 bg_notify = g_new(BackgroundNotify,1);
590
591 bg_notify->owner = owner;
592 bg_notify->trace = trace;
593 bg_notify->notify_time = notify_time;
594 if(notify_position!= NULL) {
595 bg_notify->notify_position = lttv_traceset_context_position_new(tsc);
596 lttv_traceset_context_position_copy(bg_notify->notify_position,
597 notify_position);
598 } else {
599 bg_notify->notify_position = NULL;
600 }
601 bg_notify->notify = lttv_hooks_new();
602 lttv_hooks_add_list(bg_notify->notify, notify);
603
604 *slist = g_slist_append(*slist, bg_notify);
605 }
606
607
608 static void notify_request_free(BackgroundNotify *notify_req)
609 {
610 if(notify_req == NULL) return;
611
612 if(notify_req->notify_position != NULL)
613 lttv_traceset_context_position_destroy(notify_req->notify_position);
614 if(notify_req->notify != NULL)
615 lttv_hooks_destroy(notify_req->notify);
616 g_free(notify_req);
617 }
618
619 /**
620 * Removes all the notifications requests from a specific viewer.
621 *
622 * @param owner owner of the background notification
623 */
624
625 __EXPORT void lttvwindowtraces_background_notify_remove(gpointer owner)
626 {
627 guint i;
628
629 for(i=0;i<lttvwindowtraces_get_number();i++) {
630 LttvAttribute *attribute;
631 LttvAttributeValue value;
632 LttvTrace *trace_v = lttvwindowtraces_get_trace(i);
633 GSList **slist;
634 GSList *iter = NULL;
635 gboolean result;
636
637 g_assert(trace_v != NULL);
638
639 attribute = lttv_trace_attribute(trace_v);
640
641 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
642 LTTV_NOTIFY_QUEUE,
643 LTTV_POINTER,
644 &value);
645 g_assert(result);
646
647 slist = (GSList**)(value.v_pointer);
648
649 for(iter=*slist;iter!=NULL;) {
650
651 BackgroundNotify *bg_notify = (BackgroundNotify*)iter->data;
652
653 if(bg_notify->owner == owner) {
654 GSList *rem_iter = iter;
655 iter=g_slist_next(iter);
656 notify_request_free(bg_notify);
657 *slist = g_slist_remove_link(*slist, rem_iter);
658 } else {
659 iter=g_slist_next(iter);
660 }
661 }
662
663 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
664 LTTV_NOTIFY_CURRENT,
665 LTTV_POINTER,
666 &value);
667 g_assert(result);
668
669 slist = (GSList**)(value.v_pointer);
670
671 for(iter=*slist;iter!=NULL;) {
672
673 BackgroundNotify *bg_notify = (BackgroundNotify*)iter->data;
674
675 if(bg_notify->owner == owner) {
676 GSList *rem_iter = iter;
677 iter=g_slist_next(iter);
678 notify_request_free(bg_notify);
679 *slist = g_slist_remove_link(*slist, rem_iter);
680 } else {
681 iter=g_slist_next(iter);
682 }
683 }
684 }
685 }
686
687
688 /* Background processing helper functions */
689
690 void lttvwindowtraces_add_computation_hooks(LttvAttributeName module_name,
691 LttvTracesetContext *tsc,
692 LttvHooks *hook_adder)
693 {
694 LttvAttribute *g_attribute = lttv_global_attributes();
695 LttvAttribute *module_attribute;
696 LttvAttributeType type;
697 LttvAttributeValue value;
698
699
700 module_attribute =
701 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
702 LTTV_COMPUTATION));
703 g_assert(module_attribute);
704
705 module_attribute =
706 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
707 LTTV_IATTRIBUTE(module_attribute),
708 module_name));
709 g_assert(module_attribute);
710
711 /* Call the module's hook adder */
712 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
713 LTTV_HOOK_ADDER,
714 &value);
715 if(type == LTTV_POINTER) {
716 //lttv_hooks_call((LttvHooks*)*(value.v_pointer), (gpointer)tss);
717 if(hook_adder != NULL)
718 lttv_hooks_add_list(hook_adder, (LttvHooks*)*(value.v_pointer));
719 }
720 }
721
722 void lttvwindowtraces_remove_computation_hooks(LttvAttributeName module_name,
723 LttvTracesetContext *tsc,
724 LttvHooks *hook_remover)
725 {
726 LttvAttribute *g_attribute = lttv_global_attributes();
727 LttvAttribute *module_attribute;
728 LttvAttributeType type;
729 LttvAttributeValue value;
730
731 module_attribute =
732 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
733 LTTV_COMPUTATION));
734 g_assert(module_attribute);
735
736 module_attribute =
737 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
738 LTTV_IATTRIBUTE(module_attribute),
739 module_name));
740 g_assert(module_attribute);
741
742 /* Call the module's hook remover */
743 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
744 LTTV_HOOK_REMOVER,
745 &value);
746 if(type == LTTV_POINTER) {
747 //lttv_hooks_call((LttvHooks*)*(value.v_pointer), (gpointer)tss);
748 if(hook_remover != NULL)
749 lttv_hooks_add_list(hook_remover, (LttvHooks*)*(value.v_pointer));
750 }
751 }
752
753 void lttvwindowtraces_call_before_chunk(LttvAttributeName module_name,
754 LttvTracesetContext *tsc)
755 {
756 LttvAttribute *g_attribute = lttv_global_attributes();
757 LttvAttribute *module_attribute;
758 LttvAttributeType type;
759 LttvAttributeValue value;
760 LttvHooks *before_chunk_traceset=NULL;
761 LttvHooks *before_chunk_trace=NULL;
762 LttvHooks *before_chunk_tracefile=NULL;
763 LttvHooks *event_hook=NULL;
764 LttvHooksByIdChannelArray *event_hook_by_id_channel=NULL;
765
766
767 module_attribute =
768 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
769 LTTV_COMPUTATION));
770 g_assert(module_attribute);
771
772 module_attribute =
773 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
774 LTTV_IATTRIBUTE(module_attribute),
775 module_name));
776 g_assert(module_attribute);
777
778 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
779 LTTV_BEFORE_CHUNK_TRACESET,
780 &value);
781 if(type == LTTV_POINTER) {
782 before_chunk_traceset = (LttvHooks*)*(value.v_pointer);
783 }
784
785 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
786 LTTV_BEFORE_CHUNK_TRACE,
787 &value);
788 if(type == LTTV_POINTER) {
789 before_chunk_trace = (LttvHooks*)*(value.v_pointer);
790 }
791
792 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
793 LTTV_BEFORE_CHUNK_TRACEFILE,
794 &value);
795 if(type == LTTV_POINTER) {
796 before_chunk_tracefile = (LttvHooks*)*(value.v_pointer);
797 }
798
799 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
800 LTTV_EVENT_HOOK,
801 &value);
802 if(type == LTTV_POINTER) {
803 event_hook = (LttvHooks*)*(value.v_pointer);
804 }
805
806 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
807 LTTV_EVENT_HOOK_BY_ID_CHANNEL,
808 &value);
809 if(type == LTTV_POINTER) {
810 event_hook_by_id_channel = (LttvHooksByIdChannelArray*)*(value.v_pointer);
811 }
812
813 lttv_process_traceset_begin(tsc,
814 before_chunk_traceset,
815 before_chunk_trace,
816 before_chunk_tracefile,
817 event_hook,
818 event_hook_by_id_channel);
819 }
820
821
822
823 void lttvwindowtraces_call_after_chunk(LttvAttributeName module_name,
824 LttvTracesetContext *tsc)
825 {
826 LttvAttribute *g_attribute = lttv_global_attributes();
827 LttvAttribute *module_attribute;
828 LttvAttributeType type;
829 LttvAttributeValue value;
830 LttvHooks *after_chunk_traceset=NULL;
831 LttvHooks *after_chunk_trace=NULL;
832 LttvHooks *after_chunk_tracefile=NULL;
833 LttvHooks *event_hook=NULL;
834 LttvHooksByIdChannelArray *event_hook_by_id_channel=NULL;
835
836 module_attribute =
837 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
838 LTTV_COMPUTATION));
839 g_assert(module_attribute);
840
841 module_attribute =
842 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
843 LTTV_IATTRIBUTE(module_attribute),
844 module_name));
845 g_assert(module_attribute);
846
847 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
848 LTTV_AFTER_CHUNK_TRACESET,
849 &value);
850 if(type == LTTV_POINTER) {
851 after_chunk_traceset = (LttvHooks*)*(value.v_pointer);
852 }
853
854 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
855 LTTV_AFTER_CHUNK_TRACE,
856 &value);
857 if(type == LTTV_POINTER) {
858 after_chunk_trace = (LttvHooks*)*(value.v_pointer);
859 }
860
861 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
862 LTTV_AFTER_CHUNK_TRACEFILE,
863 &value);
864 if(type == LTTV_POINTER) {
865 after_chunk_tracefile = (LttvHooks*)*(value.v_pointer);
866 }
867
868 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
869 LTTV_EVENT_HOOK,
870 &value);
871 if(type == LTTV_POINTER) {
872 event_hook = (LttvHooks*)*(value.v_pointer);
873 }
874
875 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
876 LTTV_EVENT_HOOK_BY_ID_CHANNEL,
877 &value);
878 if(type == LTTV_POINTER) {
879 event_hook_by_id_channel = (LttvHooksByIdChannelArray*)*(value.v_pointer);
880 }
881
882 lttv_process_traceset_end(tsc,
883 after_chunk_traceset,
884 after_chunk_trace,
885 after_chunk_tracefile,
886 event_hook,
887 event_hook_by_id_channel);
888
889 }
890
891
892 void lttvwindowtraces_set_in_progress(LttvAttributeName module_name,
893 LttvTrace *trace)
894 {
895 LttvAttribute *attribute = lttv_trace_attribute(trace);
896 LttvAttributeValue value;
897
898 attribute =
899 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
900 module_name));
901 g_assert(attribute);
902
903 value = lttv_iattribute_add(LTTV_IATTRIBUTE(attribute),
904 LTTV_IN_PROGRESS,
905 LTTV_INT);
906 /* the value is left unset. The only presence of the attribute is necessary.
907 */
908 }
909
910 void lttvwindowtraces_unset_in_progress(LttvAttributeName module_name,
911 LttvTrace *trace)
912 {
913 LttvAttribute *attribute = lttv_trace_attribute(trace);
914
915 attribute =
916 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
917 module_name));
918 g_assert(attribute);
919
920 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
921 LTTV_IN_PROGRESS);
922 }
923
924 __EXPORT gboolean lttvwindowtraces_get_in_progress(LttvAttributeName module_name,
925 LttvTrace *trace)
926 {
927 LttvAttribute *attribute = lttv_trace_attribute(trace);
928 LttvAttributeType type;
929 LttvAttributeValue value;
930
931 attribute =
932 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
933 module_name));
934 g_assert(attribute);
935
936 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
937 LTTV_IN_PROGRESS,
938 &value);
939 /* The only presence of the attribute is necessary. */
940 if(type == LTTV_NONE)
941 return FALSE;
942 else
943 return TRUE;
944 }
945
946 void lttvwindowtraces_set_ready(LttvAttributeName module_name,
947 LttvTrace *trace)
948 {
949 LttvAttribute *attribute = lttv_trace_attribute(trace);
950 LttvAttributeValue value;
951
952 attribute =
953 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
954 module_name));
955 g_assert(attribute);
956
957 value = lttv_iattribute_add(LTTV_IATTRIBUTE(attribute),
958 LTTV_READY,
959 LTTV_INT);
960 /* the value is left unset. The only presence of the attribute is necessary.
961 */
962 }
963
964 void lttvwindowtraces_unset_ready(LttvAttributeName module_name,
965 LttvTrace *trace)
966 {
967 LttvAttribute *attribute = lttv_trace_attribute(trace);
968
969 attribute =
970 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
971 module_name));
972 g_assert(attribute);
973
974 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
975 LTTV_READY);
976 }
977
978 __EXPORT gboolean lttvwindowtraces_get_ready(LttvAttributeName module_name,
979 LttvTrace *trace)
980 {
981 LttvAttribute *attribute = lttv_trace_attribute(trace);
982 LttvAttributeType type;
983 LttvAttributeValue value;
984
985 attribute =
986 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
987 module_name));
988 g_assert(attribute);
989
990 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
991 LTTV_READY,
992 &value);
993 /* The only presence of the attribute is necessary. */
994 if(type == LTTV_NONE)
995 return FALSE;
996 else
997 return TRUE;
998 }
999
1000 static gint find_window_widget(MainWindow *a, GtkWidget *b)
1001 {
1002 if(a->mwindow == b) return 0;
1003 else return -1;
1004 }
1005
1006
1007 /* lttvwindowtraces_process_pending_requests
1008 *
1009 * Process the pending background computation requests
1010 *
1011 * This internal function gets called by g_idle, taking care of the pending
1012 * requests.
1013 *
1014 */
1015
1016
1017 gboolean lttvwindowtraces_process_pending_requests(LttvTrace *trace)
1018 {
1019 LttvTracesetContext *tsc;
1020 LttvTracesetStats *tss;
1021 LttvTraceset *ts;
1022 //LttvTracesetContextPosition *sync_position;
1023 LttvAttribute *attribute;
1024 LttvAttribute *g_attribute = lttv_global_attributes();
1025 GSList **list_out, **list_in, **notify_in, **notify_out;
1026 LttvAttributeValue value;
1027 LttvAttributeType type;
1028 gboolean ret_val;
1029
1030 if(trace == NULL)
1031 return FALSE;
1032
1033 if(lttvwindow_preempt_count > 0) return TRUE;
1034
1035 attribute = lttv_trace_attribute(trace);
1036
1037 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
1038 LTTV_REQUESTS_QUEUE,
1039 &value);
1040 g_assert(type == LTTV_POINTER);
1041 list_out = (GSList**)(value.v_pointer);
1042
1043 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
1044 LTTV_REQUESTS_CURRENT,
1045 &value);
1046 g_assert(type == LTTV_POINTER);
1047 list_in = (GSList**)(value.v_pointer);
1048
1049 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
1050 LTTV_NOTIFY_QUEUE,
1051 &value);
1052 g_assert(type == LTTV_POINTER);
1053 notify_out = (GSList**)(value.v_pointer);
1054
1055 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
1056 LTTV_NOTIFY_CURRENT,
1057 &value);
1058 g_assert(type == LTTV_POINTER);
1059 notify_in = (GSList**)(value.v_pointer);
1060
1061 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
1062 LTTV_COMPUTATION_TRACESET,
1063 &value);
1064 g_assert(type == LTTV_POINTER);
1065 ts = (LttvTraceset*)*(value.v_pointer);
1066
1067 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
1068 LTTV_COMPUTATION_TRACESET_CONTEXT,
1069 &value);
1070 g_assert(type == LTTV_POINTER);
1071 tsc = (LttvTracesetContext*)*(value.v_pointer);
1072 tss = (LttvTracesetStats*)*(value.v_pointer);
1073 g_assert(LTTV_IS_TRACESET_CONTEXT(tsc));
1074 g_assert(LTTV_IS_TRACESET_STATS(tss));
1075 #if 0
1076 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
1077 LTTV_COMPUTATION_SYNC_POSITION,
1078 &value);
1079 g_assert(type == LTTV_POINTER);
1080 sync_position = (LttvTracesetContextPosition*)*(value.v_pointer);
1081 #endif //0
1082 /* There is no events requests pending : we should never have been called! */
1083 g_assert(g_slist_length(*list_out) != 0 || g_slist_length(*list_in) != 0);
1084 /* 0.1 Lock traces */
1085 {
1086 guint iter_trace=0;
1087
1088 for(iter_trace=0;
1089 iter_trace<lttv_traceset_number(tsc->ts);
1090 iter_trace++) {
1091 LttvTrace *trace_v = lttv_traceset_get(tsc->ts,iter_trace);
1092
1093 if(lttvwindowtraces_lock(trace_v) != 0)
1094 return TRUE; /* Cannot get trace lock, try later */
1095
1096 }
1097 }
1098 /* 0.2 Sync tracefiles */
1099 //g_assert(lttv_process_traceset_seek_position(tsc, sync_position) == 0);
1100 lttv_process_traceset_synchronize_tracefiles(tsc);
1101 /* 1. Before processing */
1102 {
1103 /* if list_in is empty */
1104 if(g_slist_length(*list_in) == 0) {
1105
1106 {
1107 /* - Add all requests in list_out to list_in, empty list_out */
1108 GSList *iter = *list_out;
1109
1110 while(iter != NULL) {
1111 gboolean remove = FALSE;
1112 gboolean free_data = FALSE;
1113
1114 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
1115
1116 remove = TRUE;
1117 free_data = FALSE;
1118 *list_in = g_slist_append(*list_in, bg_req);
1119
1120 /* Go to next */
1121 if(remove)
1122 {
1123 GSList *remove_iter = iter;
1124
1125 iter = g_slist_next(iter);
1126 if(free_data) g_free(remove_iter->data);
1127 *list_out = g_slist_remove_link(*list_out, remove_iter);
1128 } else { // not remove
1129 iter = g_slist_next(iter);
1130 }
1131 }
1132 }
1133
1134 {
1135 GSList *iter = *list_in;
1136 /* - for each request in list_in */
1137 while(iter != NULL) {
1138
1139 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
1140 /* - set hooks'in_progress flag to TRUE */
1141 lttvwindowtraces_set_in_progress(bg_req->module_name,
1142 bg_req->trace);
1143
1144 /* - call before request hook */
1145 /* Get before request hook */
1146 LttvAttribute *module_attribute;
1147
1148 module_attribute =
1149 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
1150 LTTV_IATTRIBUTE(g_attribute),
1151 LTTV_COMPUTATION));
1152 g_assert(module_attribute);
1153
1154 module_attribute =
1155 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
1156 LTTV_IATTRIBUTE(module_attribute),
1157 bg_req->module_name));
1158 g_assert(module_attribute);
1159
1160 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
1161 LTTV_BEFORE_REQUEST,
1162 &value);
1163 g_assert(type == LTTV_POINTER);
1164 LttvHooks *before_request = (LttvHooks*)*(value.v_pointer);
1165
1166 if(before_request != NULL) lttv_hooks_call(before_request, tsc);
1167
1168 iter = g_slist_next(iter);
1169 }
1170 }
1171
1172 /* - seek trace to start */
1173 {
1174 LttTime start = { 0, 0};
1175 lttv_process_traceset_seek_time(tsc, start);
1176 }
1177
1178 /* - Move all notifications from notify_out to notify_in. */
1179 {
1180 GSList *iter = *notify_out;
1181 g_assert(g_slist_length(*notify_in) == 0);
1182
1183 while(iter != NULL) {
1184 gboolean remove = FALSE;
1185 gboolean free_data = FALSE;
1186
1187 BackgroundNotify *notify_req = (BackgroundNotify*)iter->data;
1188
1189 remove = TRUE;
1190 free_data = FALSE;
1191 *notify_in = g_slist_append(*notify_in, notify_req);
1192
1193 /* Go to next */
1194 if(remove)
1195 {
1196 GSList *remove_iter = iter;
1197
1198 iter = g_slist_next(iter);
1199 if(free_data)
1200 notify_request_free((BackgroundNotify*)remove_iter->data);
1201 *notify_out = g_slist_remove_link(*notify_out, remove_iter);
1202 } else { // not remove
1203 iter = g_slist_next(iter);
1204 }
1205 }
1206 }
1207 {
1208 GSList *iter = *list_in;
1209 LttvHooks *hook_adder = lttv_hooks_new();
1210 /* - for each request in list_in */
1211 while(iter != NULL) {
1212
1213 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
1214 /*- add hooks to context*/
1215 lttvwindowtraces_add_computation_hooks(bg_req->module_name,
1216 tsc,
1217 hook_adder);
1218 iter = g_slist_next(iter);
1219 }
1220 lttv_hooks_call(hook_adder,tsc);
1221 lttv_hooks_destroy(hook_adder);
1222 }
1223
1224
1225 }
1226
1227 {
1228 GSList *iter = *list_in;
1229 /* - for each request in list_in */
1230 while(iter != NULL) {
1231
1232 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
1233 /*- Call before chunk hooks for list_in*/
1234 lttvwindowtraces_call_before_chunk(bg_req->module_name,
1235 tsc);
1236 iter = g_slist_next(iter);
1237 }
1238 }
1239
1240 }
1241 /* 2. call process traceset middle for a chunk */
1242 {
1243 /*(assert list_in is not empty! : should not even be called in that case)*/
1244 LttTime end = ltt_time_infinite;
1245 g_assert(g_slist_length(*list_in) != 0);
1246
1247 lttv_process_traceset_middle(tsc, end, CHUNK_NUM_EVENTS, NULL);
1248 }
1249
1250 /* 3. After the chunk */
1251 {
1252 /* 3.1 call after_chunk hooks for list_in */
1253 {
1254 GSList *iter = *list_in;
1255 /* - for each request in list_in */
1256 while(iter != NULL) {
1257
1258 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
1259 /* - Call after chunk hooks for list_in */
1260 lttvwindowtraces_call_after_chunk(bg_req->module_name,
1261 tsc);
1262 iter = g_slist_next(iter);
1263 }
1264 }
1265
1266 /* 3.2 for each notify_in */
1267 {
1268 GSList *iter = *notify_in;
1269 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
1270
1271 while(iter != NULL) {
1272 gboolean remove = FALSE;
1273 gboolean free_data = FALSE;
1274
1275 BackgroundNotify *notify_req = (BackgroundNotify*)iter->data;
1276
1277 /* - if current time >= notify time, call notify and remove from
1278 * notify_in.
1279 * - if current position >= notify position, call notify and remove
1280 * from notify_in.
1281 */
1282 if( (tfc != NULL &&
1283 ltt_time_compare(notify_req->notify_time, tfc->timestamp) <= 0)
1284 ||
1285 (notify_req->notify_position != NULL &&
1286 lttv_traceset_context_ctx_pos_compare(tsc,
1287 notify_req->notify_position) >= 0)
1288 ) {
1289
1290 lttv_hooks_call(notify_req->notify, notify_req);
1291
1292 remove = TRUE;
1293 free_data = TRUE;
1294 }
1295
1296 /* Go to next */
1297 if(remove)
1298 {
1299 GSList *remove_iter = iter;
1300
1301 iter = g_slist_next(iter);
1302 if(free_data)
1303 notify_request_free((BackgroundNotify*)remove_iter->data);
1304 *notify_in = g_slist_remove_link(*notify_in, remove_iter);
1305 } else { // not remove
1306 iter = g_slist_next(iter);
1307 }
1308 }
1309 }
1310
1311 {
1312 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
1313 /* 3.3 if end of trace reached */
1314 if(tfc != NULL)
1315 g_debug("Current time : %lu sec, %lu nsec",
1316 tfc->timestamp.tv_sec, tfc->timestamp.tv_nsec);
1317 if(tfc == NULL || ltt_time_compare(tfc->timestamp,
1318 tsc->time_span.end_time) > 0) {
1319
1320 {
1321 GSList *iter = *list_in;
1322 LttvHooks *hook_remover = lttv_hooks_new();
1323 /* - for each request in list_in */
1324 while(iter != NULL) {
1325
1326 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
1327 /* - remove hooks from context */
1328 lttvwindowtraces_remove_computation_hooks(bg_req->module_name,
1329 tsc,
1330 hook_remover);
1331 iter = g_slist_next(iter);
1332 }
1333 lttv_hooks_call(hook_remover,tsc);
1334 lttv_hooks_destroy(hook_remover);
1335 }
1336
1337 /* - for each request in list_in */
1338 {
1339 GSList *iter = *list_in;
1340
1341 while(iter != NULL) {
1342 gboolean remove = FALSE;
1343 gboolean free_data = FALSE;
1344
1345 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
1346
1347 /* - set hooks'in_progress flag to FALSE */
1348 lttvwindowtraces_unset_in_progress(bg_req->module_name,
1349 bg_req->trace);
1350 /* - set hooks'ready flag to TRUE */
1351 lttvwindowtraces_set_ready(bg_req->module_name,
1352 bg_req->trace);
1353 /* - call after request hook */
1354 /* Get after request hook */
1355 LttvAttribute *module_attribute;
1356
1357 module_attribute =
1358 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
1359 LTTV_IATTRIBUTE(g_attribute),
1360 LTTV_COMPUTATION));
1361 g_assert(module_attribute);
1362
1363 module_attribute =
1364 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
1365 LTTV_IATTRIBUTE(module_attribute),
1366 bg_req->module_name));
1367 g_assert(module_attribute);
1368
1369 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(module_attribute),
1370 LTTV_AFTER_REQUEST,
1371 &value);
1372 g_assert(type == LTTV_POINTER);
1373 LttvHooks *after_request = (LttvHooks*)*(value.v_pointer);
1374 {
1375 struct sum_traceset_closure t_closure;
1376 t_closure.tss = (LttvTracesetStats*)tsc;
1377 t_closure.current_time = ltt_time_infinite;
1378 if(after_request != NULL) lttv_hooks_call(after_request,
1379 &t_closure);
1380 }
1381
1382 if(bg_req->dialog != NULL)
1383 gtk_widget_destroy(bg_req->dialog);
1384 GtkWidget *parent_window;
1385 if(g_slist_find_custom(g_main_window_list,
1386 bg_req->parent_window,
1387 (GCompareFunc)find_window_widget))
1388 parent_window = GTK_WIDGET(bg_req->parent_window);
1389 else
1390 parent_window = NULL;
1391
1392 GtkWidget *dialog =
1393 gtk_message_dialog_new(GTK_WINDOW(parent_window),
1394 GTK_DIALOG_DESTROY_WITH_PARENT,
1395 GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
1396 "Background computation %s finished for trace %s",
1397 g_quark_to_string(bg_req->module_name),
1398 g_quark_to_string(ltt_trace_name(lttv_trace(bg_req->trace))));
1399 if(parent_window != NULL)
1400 gtk_window_set_transient_for(GTK_WINDOW(dialog),
1401 GTK_WINDOW(parent_window));
1402 g_signal_connect_swapped (dialog, "response",
1403 G_CALLBACK (gtk_widget_destroy),
1404 dialog);
1405 gtk_widget_show(dialog);
1406
1407 /* - remove request */
1408 remove = TRUE;
1409 free_data = TRUE;
1410
1411 /* Go to next */
1412 if(remove)
1413 {
1414 GSList *remove_iter = iter;
1415
1416 iter = g_slist_next(iter);
1417 if(free_data) g_free(remove_iter->data);
1418 *list_in = g_slist_remove_link(*list_in, remove_iter);
1419 } else { // not remove
1420 iter = g_slist_next(iter);
1421 }
1422 }
1423 }
1424
1425 /* - for each notifications in notify_in */
1426 {
1427 GSList *iter = *notify_in;
1428
1429 while(iter != NULL) {
1430 gboolean remove = FALSE;
1431 gboolean free_data = FALSE;
1432
1433 BackgroundNotify *notify_req = (BackgroundNotify*)iter->data;
1434
1435 /* - call notify and remove from notify_in */
1436 lttv_hooks_call(notify_req->notify, notify_req);
1437 remove = TRUE;
1438 free_data = TRUE;
1439
1440 /* Go to next */
1441 if(remove)
1442 {
1443 GSList *remove_iter = iter;
1444
1445 iter = g_slist_next(iter);
1446 if(free_data)
1447 notify_request_free((BackgroundNotify*)remove_iter->data);
1448 *notify_in = g_slist_remove_link(*notify_in, remove_iter);
1449 } else { // not remove
1450 iter = g_slist_next(iter);
1451 }
1452 }
1453 }
1454 {
1455 /* - reset the context */
1456 LTTV_TRACESET_CONTEXT_GET_CLASS(tsc)->fini(tsc);
1457 LTTV_TRACESET_CONTEXT_GET_CLASS(tsc)->init(tsc,ts);
1458 }
1459 /* - if list_out is empty */
1460 if(g_slist_length(*list_out) == 0) {
1461 /* - return FALSE (scheduler stopped) */
1462 g_debug("Background computation scheduler stopped");
1463 g_info("Background computation finished for trace %p", trace);
1464 /* FIXME : remove status bar info, need context id and message id */
1465
1466 ret_val = FALSE;
1467 } else {
1468 ret_val = TRUE;
1469 }
1470 } else {
1471 /* 3.4 else, end of trace not reached */
1472 /* - return TRUE (scheduler still registered) */
1473 g_debug("Background computation left");
1474 ret_val = TRUE;
1475 }
1476 }
1477 }
1478 /* 4. Unlock traces */
1479 {
1480 lttv_process_traceset_get_sync_data(tsc);
1481 //lttv_traceset_context_position_save(tsc, sync_position);
1482 guint iter_trace;
1483
1484 for(iter_trace=0;
1485 iter_trace<lttv_traceset_number(tsc->ts);
1486 iter_trace++) {
1487 LttvTrace *trace_v = lttv_traceset_get(tsc->ts, iter_trace);
1488
1489 lttvwindowtraces_unlock(trace_v);
1490 }
1491 }
1492 return ret_val;
1493 }
1494
1495
1496
1497 /**
1498 * Register the background computation hooks for a specific module. It adds the
1499 * computation hooks to the global attrubutes, under "computation/module name".
1500 *
1501 * @param module_name A GQuark : the name of the module which computes the
1502 * information.
1503 */
1504 void lttvwindowtraces_register_computation_hooks(LttvAttributeName module_name,
1505 LttvHooks *before_chunk_traceset,
1506 LttvHooks *before_chunk_trace,
1507 LttvHooks *before_chunk_tracefile,
1508 LttvHooks *after_chunk_traceset,
1509 LttvHooks *after_chunk_trace,
1510 LttvHooks *after_chunk_tracefile,
1511 LttvHooks *before_request,
1512 LttvHooks *after_request,
1513 LttvHooks *event_hook,
1514 LttvHooksById *event_hook_by_id_channel,
1515 LttvHooks *hook_adder,
1516 LttvHooks *hook_remover)
1517 {
1518 LttvAttribute *g_attribute = lttv_global_attributes();
1519 LttvAttribute *attribute;
1520 LttvAttributeValue value;
1521 gboolean result;
1522
1523 attribute =
1524 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
1525 LTTV_COMPUTATION));
1526 g_assert(attribute);
1527
1528 attribute =
1529 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
1530 module_name));
1531 g_assert(attribute);
1532
1533 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1534 LTTV_BEFORE_CHUNK_TRACESET,
1535 LTTV_POINTER,
1536 &value);
1537 g_assert(result);
1538
1539 *(value.v_pointer) = before_chunk_traceset;
1540
1541 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1542 LTTV_BEFORE_CHUNK_TRACE,
1543 LTTV_POINTER,
1544 &value);
1545 g_assert(result);
1546 *(value.v_pointer) = before_chunk_trace;
1547
1548 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1549 LTTV_BEFORE_CHUNK_TRACEFILE,
1550 LTTV_POINTER,
1551 &value);
1552 g_assert(result);
1553 *(value.v_pointer) = before_chunk_tracefile;
1554
1555 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1556 LTTV_AFTER_CHUNK_TRACESET,
1557 LTTV_POINTER,
1558 &value);
1559 g_assert(result);
1560 *(value.v_pointer) = after_chunk_traceset;
1561
1562 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1563 LTTV_AFTER_CHUNK_TRACE,
1564 LTTV_POINTER,
1565 &value);
1566 g_assert(result);
1567 *(value.v_pointer) = after_chunk_trace;
1568
1569 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1570 LTTV_AFTER_CHUNK_TRACEFILE,
1571 LTTV_POINTER,
1572 &value);
1573 g_assert(result);
1574 *(value.v_pointer) = after_chunk_tracefile;
1575
1576 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1577 LTTV_BEFORE_REQUEST,
1578 LTTV_POINTER,
1579 &value);
1580 g_assert(result);
1581 *(value.v_pointer) = before_request;
1582
1583 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1584 LTTV_AFTER_REQUEST,
1585 LTTV_POINTER,
1586 &value);
1587 g_assert(result);
1588 *(value.v_pointer) = after_request;
1589
1590 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1591 LTTV_EVENT_HOOK,
1592 LTTV_POINTER,
1593 &value);
1594 g_assert(result);
1595 *(value.v_pointer) = event_hook;
1596
1597 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1598 LTTV_EVENT_HOOK_BY_ID_CHANNEL,
1599 LTTV_POINTER,
1600 &value);
1601 g_assert(result);
1602 *(value.v_pointer) = event_hook_by_id_channel;
1603
1604 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1605 LTTV_HOOK_ADDER,
1606 LTTV_POINTER,
1607 &value);
1608 g_assert(result);
1609 *(value.v_pointer) = hook_adder;
1610
1611 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1612 LTTV_HOOK_REMOVER,
1613 LTTV_POINTER,
1614 &value);
1615 g_assert(result);
1616 *(value.v_pointer) = hook_remover;
1617
1618 }
1619
1620
1621 /**
1622 * It removes all the requests that can be currently processed by the
1623 * background computation algorithm for all the traces (list_in and list_out).
1624 *
1625 * Leaves the flag to in_progress or none.. depending if current or queue
1626 *
1627 * @param module_name A GQuark : the name of the module which computes the
1628 * information.
1629 */
1630 void lttvwindowtraces_unregister_requests(LttvAttributeName module_name)
1631 {
1632 guint i;
1633 gboolean result;
1634
1635 for(i=0;i<lttvwindowtraces_get_number();i++) {
1636 LttvTrace *trace_v = lttvwindowtraces_get_trace(i);
1637 g_assert(trace_v != NULL);
1638 LttvAttribute *attribute = lttv_trace_attribute(trace_v);
1639 LttvAttributeValue value;
1640 GSList **queue, **current;
1641 GSList *iter;
1642
1643 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1644 LTTV_REQUESTS_QUEUE,
1645 LTTV_POINTER,
1646 &value);
1647 g_assert(result);
1648
1649 queue = (GSList**)(value.v_pointer);
1650
1651 iter = *queue;
1652 while(iter != NULL) {
1653 gboolean remove = FALSE;
1654 gboolean free_data = FALSE;
1655
1656 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
1657
1658 if(bg_req->module_name == module_name) {
1659 remove = TRUE;
1660 free_data = TRUE;
1661 }
1662
1663 /* Go to next */
1664 if(remove)
1665 {
1666 GSList *remove_iter = iter;
1667
1668 iter = g_slist_next(iter);
1669 if(free_data) g_free(remove_iter->data);
1670 *queue = g_slist_remove_link(*queue, remove_iter);
1671 } else { // not remove
1672 iter = g_slist_next(iter);
1673 }
1674 }
1675
1676
1677 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1678 LTTV_REQUESTS_CURRENT,
1679 LTTV_POINTER,
1680 &value);
1681 g_assert(result);
1682
1683 current = (GSList**)(value.v_pointer);
1684
1685 iter = *current;
1686 while(iter != NULL) {
1687 gboolean remove = FALSE;
1688 gboolean free_data = FALSE;
1689
1690 BackgroundRequest *bg_req = (BackgroundRequest*)iter->data;
1691
1692 if(bg_req->module_name == module_name) {
1693 remove = TRUE;
1694 free_data = TRUE;
1695 }
1696
1697 /* Go to next */
1698 if(remove)
1699 {
1700 GSList *remove_iter = iter;
1701
1702 iter = g_slist_next(iter);
1703 if(free_data) g_free(remove_iter->data);
1704 *current = g_slist_remove_link(*current, remove_iter);
1705 } else { // not remove
1706 iter = g_slist_next(iter);
1707 }
1708 }
1709 }
1710 }
1711
1712
1713 /**
1714 * Unregister the background computation hooks for a specific module.
1715 *
1716 * It also removes all the requests that can be currently processed by the
1717 * background computation algorithm for all the traces (list_in and list_out).
1718 *
1719 * @param module_name A GQuark : the name of the module which computes the
1720 * information.
1721 */
1722
1723 void lttvwindowtraces_unregister_computation_hooks
1724 (LttvAttributeName module_name)
1725 {
1726 LttvAttribute *g_attribute = lttv_global_attributes();
1727 LttvAttribute *attribute;
1728 LttvAttributeValue value;
1729 gboolean result;
1730
1731 attribute =
1732 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
1733 LTTV_COMPUTATION));
1734 g_assert(attribute);
1735
1736 attribute =
1737 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(attribute),
1738 module_name));
1739 g_assert(attribute);
1740
1741 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1742 LTTV_BEFORE_CHUNK_TRACESET,
1743 LTTV_POINTER,
1744 &value);
1745 g_assert(result);
1746
1747 LttvHooks *before_chunk_traceset = (LttvHooks*)*(value.v_pointer);
1748 if(before_chunk_traceset != NULL)
1749 lttv_hooks_destroy(before_chunk_traceset);
1750
1751 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1752 LTTV_BEFORE_CHUNK_TRACE,
1753 LTTV_POINTER,
1754 &value);
1755 g_assert(result);
1756
1757 LttvHooks *before_chunk_trace = (LttvHooks*)*(value.v_pointer);
1758 if(before_chunk_trace != NULL)
1759 lttv_hooks_destroy(before_chunk_trace);
1760
1761 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1762 LTTV_BEFORE_CHUNK_TRACEFILE,
1763 LTTV_POINTER,
1764 &value);
1765 g_assert(result);
1766
1767 LttvHooks *before_chunk_tracefile = (LttvHooks*)*(value.v_pointer);
1768 if(before_chunk_tracefile != NULL)
1769 lttv_hooks_destroy(before_chunk_tracefile);
1770
1771 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1772 LTTV_AFTER_CHUNK_TRACESET,
1773 LTTV_POINTER,
1774 &value);
1775 g_assert(result);
1776
1777 LttvHooks *after_chunk_traceset = (LttvHooks*)*(value.v_pointer);
1778 if(after_chunk_traceset != NULL)
1779 lttv_hooks_destroy(after_chunk_traceset);
1780
1781 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1782 LTTV_AFTER_CHUNK_TRACE,
1783 LTTV_POINTER,
1784 &value);
1785 g_assert(result);
1786
1787 LttvHooks *after_chunk_trace = (LttvHooks*)*(value.v_pointer);
1788 if(after_chunk_trace != NULL)
1789 lttv_hooks_destroy(after_chunk_trace);
1790
1791 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1792 LTTV_AFTER_CHUNK_TRACEFILE,
1793 LTTV_POINTER,
1794 &value);
1795 g_assert(result);
1796
1797 LttvHooks *after_chunk_tracefile = (LttvHooks*)*(value.v_pointer);
1798 if(after_chunk_tracefile != NULL)
1799 lttv_hooks_destroy(after_chunk_tracefile);
1800
1801 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1802 LTTV_BEFORE_REQUEST,
1803 LTTV_POINTER,
1804 &value);
1805 g_assert(result);
1806
1807 LttvHooks *before_request = (LttvHooks*)*(value.v_pointer);
1808 if(before_request != NULL)
1809 lttv_hooks_destroy(before_request);
1810
1811 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1812 LTTV_AFTER_REQUEST,
1813 LTTV_POINTER,
1814 &value);
1815 g_assert(result);
1816
1817 LttvHooks *after_request = (LttvHooks*)*(value.v_pointer);
1818 if(after_request != NULL)
1819 lttv_hooks_destroy(after_request);
1820
1821 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1822 LTTV_EVENT_HOOK,
1823 LTTV_POINTER,
1824 &value);
1825 g_assert(result);
1826
1827 LttvHooks *event_hook = (LttvHooks*)*(value.v_pointer);
1828 if(event_hook != NULL)
1829 lttv_hooks_destroy(event_hook);
1830
1831 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1832 LTTV_EVENT_HOOK_BY_ID_CHANNEL,
1833 LTTV_POINTER,
1834 &value);
1835 g_assert(result);
1836
1837 LttvHooksByIdChannelArray *event_hook_by_id_channel = (LttvHooksByIdChannelArray*)*(value.v_pointer);
1838 if(event_hook_by_id_channel != NULL)
1839 lttv_hooks_by_id_channel_destroy(event_hook_by_id_channel);
1840
1841 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1842 LTTV_HOOK_ADDER,
1843 LTTV_POINTER,
1844 &value);
1845 g_assert(result);
1846
1847 LttvHooks *hook_adder = (LttvHooks*)*(value.v_pointer);
1848 if(hook_adder != NULL)
1849 lttv_hooks_destroy(hook_adder);
1850
1851 result = lttv_iattribute_find(LTTV_IATTRIBUTE(attribute),
1852 LTTV_HOOK_REMOVER,
1853 LTTV_POINTER,
1854 &value);
1855 g_assert(result);
1856
1857 LttvHooks *hook_remover = (LttvHooks*)*(value.v_pointer);
1858 if(hook_remover != NULL)
1859 lttv_hooks_destroy(hook_remover);
1860
1861
1862 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1863 LTTV_EVENT_HOOK_BY_ID_CHANNEL);
1864 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1865 LTTV_EVENT_HOOK);
1866
1867 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1868 LTTV_AFTER_REQUEST);
1869 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1870 LTTV_BEFORE_REQUEST);
1871
1872 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1873 LTTV_AFTER_CHUNK_TRACEFILE);
1874 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1875 LTTV_AFTER_CHUNK_TRACE);
1876 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1877 LTTV_AFTER_CHUNK_TRACESET);
1878
1879 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1880 LTTV_BEFORE_CHUNK_TRACEFILE);
1881 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1882 LTTV_BEFORE_CHUNK_TRACE);
1883 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1884 LTTV_BEFORE_CHUNK_TRACESET);
1885 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1886 LTTV_HOOK_ADDER);
1887 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1888 LTTV_HOOK_REMOVER);
1889
1890 /* finally, remove module name */
1891 attribute =
1892 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(LTTV_IATTRIBUTE(g_attribute),
1893 LTTV_COMPUTATION));
1894 g_assert(attribute);
1895 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1896 module_name);
1897
1898 }
1899
1900 /**
1901 * Lock a trace so no other instance can use it.
1902 *
1903 * @param trace The trace to lock.
1904 * @return 0 on success, -1 if cannot get lock.
1905 */
1906 gint lttvwindowtraces_lock(LttvTrace *trace)
1907 {
1908 LttvAttribute *attribute = lttv_trace_attribute(trace);
1909 LttvAttributeValue value;
1910 LttvAttributeType type;
1911
1912 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
1913 LTTV_LOCK,
1914 &value);
1915 /* Verify the absence of the lock. */
1916 if(type != LTTV_NONE) {
1917 g_critical("Cannot take trace lock");
1918 return -1;
1919 }
1920
1921 value = lttv_iattribute_add(LTTV_IATTRIBUTE(attribute),
1922 LTTV_LOCK,
1923 LTTV_INT);
1924 /* the value is left unset. The only presence of the attribute is necessary.
1925 */
1926
1927 return 0;
1928 }
1929
1930 /**
1931 * Unlock a trace.
1932 *
1933 * @param trace The trace to unlock.
1934 * @return 0 on success, -1 if cannot unlock (not locked ?).
1935 */
1936 gint lttvwindowtraces_unlock(LttvTrace *trace)
1937 {
1938 LttvAttribute *attribute = lttv_trace_attribute(trace);
1939 LttvAttributeType type;
1940 LttvAttributeValue value;
1941
1942 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
1943 LTTV_LOCK,
1944 &value);
1945 /* Verify the presence of the lock. */
1946 if(type == LTTV_NONE) {
1947 g_critical("Cannot release trace lock");
1948 return -1;
1949 }
1950
1951 lttv_iattribute_remove_by_name(LTTV_IATTRIBUTE(attribute),
1952 LTTV_LOCK);
1953
1954 return 0;
1955 }
1956
1957 /**
1958 * Verify if a trace is locked.
1959 *
1960 * @param trace The trace to verify.
1961 * @return TRUE if locked, FALSE is unlocked.
1962 */
1963 gint lttvwindowtraces_get_lock_state(LttvTrace *trace)
1964 {
1965 LttvAttribute *attribute = lttv_trace_attribute(trace);
1966 LttvAttributeType type;
1967 LttvAttributeValue value;
1968
1969 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
1970 LTTV_LOCK,
1971 &value);
1972 /* The only presence of the attribute is necessary. */
1973 if(type == LTTV_NONE)
1974 return FALSE;
1975 else
1976 return TRUE;
1977 }
1978
This page took 0.112501 seconds and 3 git commands to generate.