uninitialized variables checked, plus O2 optimisations checked : strict aliasing...
[lttv.git] / ltt / branches / poly / lttv / lttv / tracecontext.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
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 #include <string.h>
20 #include <lttv/tracecontext.h>
21 #include <ltt/event.h>
22 #include <ltt/facility.h>
23 #include <ltt/trace.h>
24 #include <ltt/type.h>
25
26
27
28
29 gint compare_tracefile(gconstpointer a, gconstpointer b)
30 {
31 gint comparison;
32
33 const LttvTracefileContext *trace_a = (const LttvTracefileContext *)a;
34
35 const LttvTracefileContext *trace_b = (const LttvTracefileContext *)b;
36
37 if(trace_a == trace_b) return 0;
38 comparison = ltt_time_compare(trace_a->timestamp, trace_b->timestamp);
39 if(comparison != 0) return comparison;
40 if(trace_a->index < trace_b->index) return -1;
41 else if(trace_a->index > trace_b->index) return 1;
42 if(trace_a->t_context->index < trace_b->t_context->index) return -1;
43 else if(trace_a->t_context->index > trace_b->t_context->index) return 1;
44
45 g_assert(FALSE);
46 return 0; /* This should never happen */
47 }
48
49 struct _LttvTraceContextPosition {
50 LttEventPosition **tf_pos; /* Position in each tracefile */
51 guint nb_tracefile; /* Number of tracefiles (check) */
52 };
53
54 struct _LttvTracesetContextPosition {
55 LttvTraceContextPosition *t_pos; /* Position in each trace */
56 guint nb_trace; /* Number of traces (check) */
57 LttTime timestamp; /* Current time at the saved position */
58 };
59
60 void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts)
61 {
62 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts);
63 }
64
65
66 void lttv_context_fini(LttvTracesetContext *self)
67 {
68 LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self);
69 }
70
71
72 LttvTracesetContext *
73 lttv_context_new_traceset_context(LttvTracesetContext *self)
74 {
75 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self);
76 }
77
78
79
80
81 LttvTraceContext *
82 lttv_context_new_trace_context(LttvTracesetContext *self)
83 {
84 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
85 }
86
87
88 LttvTracefileContext *
89 lttv_context_new_tracefile_context(LttvTracesetContext *self)
90 {
91 return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
92 }
93
94 /****************************************************************************
95 * lttv_traceset_context_compute_time_span
96 *
97 * Keep the time span is sync with on the fly addition and removal of traces
98 * in a trace set. It must be called each time a trace is added/removed from
99 * the traceset. It could be more efficient to call it only once a bunch
100 * of traces are loaded, but the calculation is not long, so it's not
101 * critical.
102 *
103 * Author : Xang Xiu Yang
104 ***************************************************************************/
105 static void lttv_traceset_context_compute_time_span(
106 LttvTracesetContext *self,
107 TimeInterval *time_span)
108 {
109 LttvTraceset * traceset = self->ts;
110 int numTraces = lttv_traceset_number(traceset);
111 int i;
112 LttTime s, e;
113 LttvTraceContext *tc;
114 LttTrace * trace;
115
116 time_span->start_time.tv_sec = 0;
117 time_span->start_time.tv_nsec = 0;
118 time_span->end_time.tv_sec = 0;
119 time_span->end_time.tv_nsec = 0;
120
121 for(i=0; i<numTraces;i++){
122 tc = self->traces[i];
123 trace = tc->t;
124
125 ltt_trace_time_span_get(trace, &s, &e);
126
127 if(i==0){
128 time_span->start_time = s;
129 time_span->end_time = e;
130 }else{
131 if(s.tv_sec < time_span->start_time.tv_sec
132 || (s.tv_sec == time_span->start_time.tv_sec
133 && s.tv_nsec < time_span->start_time.tv_nsec))
134 time_span->start_time = s;
135 if(e.tv_sec > time_span->end_time.tv_sec
136 || (e.tv_sec == time_span->end_time.tv_sec
137 && e.tv_nsec > time_span->end_time.tv_nsec))
138 time_span->end_time = e;
139 }
140 }
141 }
142
143
144 static void
145 init(LttvTracesetContext *self, LttvTraceset *ts)
146 {
147 guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
148
149 LttvTraceContext *tc;
150
151 LttvTracefileContext *tfc;
152
153 LttTime null_time = {0, 0};
154
155 nb_trace = lttv_traceset_number(ts);
156 self->ts = ts;
157 self->traces = g_new(LttvTraceContext *, nb_trace);
158 self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
159 self->ts_a = lttv_traceset_attribute(ts);
160 for(i = 0 ; i < nb_trace ; i++) {
161 tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
162 self->traces[i] = tc;
163
164 tc->ts_context = self;
165 tc->index = i;
166 tc->vt = lttv_traceset_get(ts, i);
167 tc->t = lttv_trace(tc->vt);
168 tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
169 tc->t_a = lttv_trace_attribute(tc->vt);
170 nb_control = ltt_trace_control_tracefile_number(tc->t);
171 nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t);
172 nb_tracefile = nb_control + nb_per_cpu;
173 tc->tracefiles = g_new(LttvTracefileContext *, nb_tracefile);
174
175 for(j = 0 ; j < nb_tracefile ; j++) {
176 tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
177 tc->tracefiles[j] = tfc;
178 tfc->index = j;
179
180 if(j < nb_control) {
181 tfc->control = TRUE;
182 tfc->tf = ltt_trace_control_tracefile_get(tc->t, j);
183 }
184 else {
185 tfc->control = FALSE;
186 tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control);
187 }
188 tfc->t_context = tc;
189 tfc->e = ltt_event_new();
190 tfc->event = lttv_hooks_new();
191 tfc->event_by_id = lttv_hooks_by_id_new();
192 tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
193 }
194 }
195 self->pqueue = g_tree_new(compare_tracefile);
196 lttv_process_traceset_seek_time(self, null_time);
197 lttv_traceset_context_compute_time_span(self, &self->time_span);
198
199 }
200
201
202 void fini(LttvTracesetContext *self)
203 {
204 guint i, j, nb_trace, nb_tracefile;
205
206 LttvTraceContext *tc;
207
208 LttvTracefileContext *tfc;
209
210 LttvTraceset *ts = self->ts;
211
212 //FIXME : segfault
213
214 g_tree_destroy(self->pqueue);
215 g_object_unref(self->a);
216
217 nb_trace = lttv_traceset_number(ts);
218
219 for(i = 0 ; i < nb_trace ; i++) {
220 tc = self->traces[i];
221
222 g_object_unref(tc->a);
223
224 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
225 ltt_trace_per_cpu_tracefile_number(tc->t);
226
227 for(j = 0 ; j < nb_tracefile ; j++) {
228 tfc = tc->tracefiles[j];
229 ltt_event_destroy(tfc->e);
230 lttv_hooks_destroy(tfc->event);
231 lttv_hooks_by_id_destroy(tfc->event_by_id);
232 g_object_unref(tfc->a);
233 g_object_unref(tfc);
234 }
235 g_free(tc->tracefiles);
236 g_object_unref(tc);
237 }
238 g_free(self->traces);
239 }
240
241
242 void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
243 LttvHooks *before_traceset,
244 LttvHooks *before_trace,
245 LttvHooks *before_tracefile,
246 LttvHooks *event,
247 LttvHooksById *event_by_id)
248 {
249 LttvTraceset *ts = self->ts;
250
251 guint i, nb_trace;
252
253 LttvTraceContext *tc;
254
255 lttv_hooks_call(before_traceset, self);
256
257 nb_trace = lttv_traceset_number(ts);
258
259 for(i = 0 ; i < nb_trace ; i++) {
260 tc = self->traces[i];
261 lttv_trace_context_add_hooks(tc,
262 before_trace,
263 before_tracefile,
264 event,
265 event_by_id);
266 }
267 }
268
269
270 void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
271 LttvHooks *after_traceset,
272 LttvHooks *after_trace,
273 LttvHooks *after_tracefile,
274 LttvHooks *event,
275 LttvHooksById *event_by_id)
276 {
277
278 LttvTraceset *ts = self->ts;
279
280 guint i, nb_trace;
281
282 LttvTraceContext *tc;
283
284 nb_trace = lttv_traceset_number(ts);
285
286 for(i = 0 ; i < nb_trace ; i++) {
287 tc = self->traces[i];
288 lttv_trace_context_remove_hooks(tc,
289 after_trace,
290 after_tracefile,
291 event,
292 event_by_id);
293 }
294
295 lttv_hooks_call(after_traceset, self);
296
297
298 }
299
300 void lttv_trace_context_add_hooks(LttvTraceContext *self,
301 LttvHooks *before_trace,
302 LttvHooks *before_tracefile,
303 LttvHooks *event,
304 LttvHooksById *event_by_id)
305 {
306 guint i, nb_tracefile;
307
308 LttvTracefileContext *tfc;
309
310 lttv_hooks_call(before_trace, self);
311 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
312 ltt_trace_per_cpu_tracefile_number(self->t);
313
314 for(i = 0 ; i < nb_tracefile ; i++) {
315 tfc = self->tracefiles[i];
316 lttv_tracefile_context_add_hooks(tfc,
317 before_tracefile,
318 event,
319 event_by_id);
320 }
321 }
322
323
324
325 void lttv_trace_context_remove_hooks(LttvTraceContext *self,
326 LttvHooks *after_trace,
327 LttvHooks *after_tracefile,
328 LttvHooks *event,
329 LttvHooksById *event_by_id)
330 {
331 guint i, nb_tracefile;
332
333 LttvTracefileContext *tfc;
334
335 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
336 ltt_trace_per_cpu_tracefile_number(self->t);
337
338 for(i = 0 ; i < nb_tracefile ; i++) {
339 tfc = self->tracefiles[i];
340 lttv_tracefile_context_remove_hooks(tfc,
341 after_tracefile,
342 event,
343 event_by_id);
344 }
345
346 lttv_hooks_call(after_trace, self);
347 }
348
349 void lttv_tracefile_context_add_hooks(LttvTracefileContext *self,
350 LttvHooks *before_tracefile,
351 LttvHooks *event,
352 LttvHooksById *event_by_id)
353 {
354 guint i;
355
356 LttvHooks *hook;
357
358 lttv_hooks_call(before_tracefile, self);
359 lttv_hooks_add_list(self->event, event);
360 if(event_by_id != NULL)
361 for(i = 0; i < lttv_hooks_by_id_max_id(event_by_id); i++) {
362 hook = lttv_hooks_by_id_get(self->event_by_id, i);
363 if(hook != NULL)
364 lttv_hooks_remove_list(hook, lttv_hooks_by_id_get(event_by_id, i));
365 }
366
367 }
368
369 void lttv_tracefile_context_remove_hooks(LttvTracefileContext *self,
370 LttvHooks *after_tracefile,
371 LttvHooks *event,
372 LttvHooksById *event_by_id)
373 {
374 guint i;
375
376 LttvHooks *hook;
377
378
379 lttv_hooks_remove_list(self->event, event);
380 if(event_by_id != NULL)
381 for(i = 0; i < lttv_hooks_by_id_max_id(event_by_id); i++) {
382 hook = lttv_hooks_by_id_find(self->event_by_id, i);
383 lttv_hooks_add_list(hook, lttv_hooks_by_id_get(event_by_id, i));
384 }
385
386 lttv_hooks_call(after_tracefile, self);
387 }
388
389
390
391 void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc,
392 unsigned i,
393 LttvHooks *event_by_id)
394 {
395 LttvHooks * h;
396 h = lttv_hooks_by_id_find(tfc->event_by_id, i);
397 lttv_hooks_add_list(h, event_by_id);
398 }
399
400 void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc,
401 unsigned i)
402 {
403 lttv_hooks_by_id_remove(tfc->event_by_id, i);
404 }
405
406 static LttvTracesetContext *
407 new_traceset_context(LttvTracesetContext *self)
408 {
409 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
410 }
411
412
413 static LttvTraceContext *
414 new_trace_context(LttvTracesetContext *self)
415 {
416 return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
417 }
418
419
420 static LttvTracefileContext *
421 new_tracefile_context(LttvTracesetContext *self)
422 {
423 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
424 }
425
426
427 static void
428 traceset_context_instance_init (GTypeInstance *instance, gpointer g_class)
429 {
430 /* Be careful of anything which would not work well with shallow copies */
431 }
432
433
434 static void
435 traceset_context_finalize (LttvTracesetContext *self)
436 {
437 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
438 ->finalize(G_OBJECT(self));
439 }
440
441
442 static void
443 traceset_context_class_init (LttvTracesetContextClass *klass)
444 {
445 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
446
447 gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
448 klass->init = init;
449 klass->fini = fini;
450 klass->new_traceset_context = new_traceset_context;
451 klass->new_trace_context = new_trace_context;
452 klass->new_tracefile_context = new_tracefile_context;
453 }
454
455
456 GType
457 lttv_traceset_context_get_type(void)
458 {
459 static GType type = 0;
460 if (type == 0) {
461 static const GTypeInfo info = {
462 sizeof (LttvTracesetContextClass),
463 NULL, /* base_init */
464 NULL, /* base_finalize */
465 (GClassInitFunc) traceset_context_class_init, /* class_init */
466 NULL, /* class_finalize */
467 NULL, /* class_data */
468 sizeof (LttvTracesetContext),
469 0, /* n_preallocs */
470 (GInstanceInitFunc) traceset_context_instance_init, /* instance_init */
471 NULL /* Value handling */
472 };
473
474 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
475 &info, 0);
476 }
477 return type;
478 }
479
480
481 static void
482 trace_context_instance_init (GTypeInstance *instance, gpointer g_class)
483 {
484 /* Be careful of anything which would not work well with shallow copies */
485 }
486
487
488 static void
489 trace_context_finalize (LttvTraceContext *self)
490 {
491 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
492 finalize(G_OBJECT(self));
493 }
494
495
496 static void
497 trace_context_class_init (LttvTraceContextClass *klass)
498 {
499 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
500
501 gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
502 }
503
504
505 GType
506 lttv_trace_context_get_type(void)
507 {
508 static GType type = 0;
509 if (type == 0) {
510 static const GTypeInfo info = {
511 sizeof (LttvTraceContextClass),
512 NULL, /* base_init */
513 NULL, /* base_finalize */
514 (GClassInitFunc) trace_context_class_init, /* class_init */
515 NULL, /* class_finalize */
516 NULL, /* class_data */
517 sizeof (LttvTraceContext),
518 0, /* n_preallocs */
519 (GInstanceInitFunc) trace_context_instance_init, /* instance_init */
520 NULL /* Value handling */
521 };
522
523 type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
524 &info, 0);
525 }
526 return type;
527 }
528
529
530 static void
531 tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class)
532 {
533 /* Be careful of anything which would not work well with shallow copies */
534 }
535
536
537 static void
538 tracefile_context_finalize (LttvTracefileContext *self)
539 {
540 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
541 ->finalize(G_OBJECT(self));
542 }
543
544
545 static void
546 tracefile_context_class_init (LttvTracefileContextClass *klass)
547 {
548 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
549
550 gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
551 }
552
553
554 GType
555 lttv_tracefile_context_get_type(void)
556 {
557 static GType type = 0;
558 if (type == 0) {
559 static const GTypeInfo info = {
560 sizeof (LttvTracefileContextClass),
561 NULL, /* base_init */
562 NULL, /* base_finalize */
563 (GClassInitFunc) tracefile_context_class_init, /* class_init */
564 NULL, /* class_finalize */
565 NULL, /* class_data */
566 sizeof (LttvTracefileContext),
567 0, /* n_preallocs */
568 (GInstanceInitFunc) tracefile_context_instance_init, /* instance_init */
569 NULL /* Value handling */
570 };
571
572 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType",
573 &info, 0);
574 }
575 return type;
576 }
577
578
579
580 gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
581 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
582 return TRUE;
583 }
584
585
586 /* Put all the tracefiles at the tracefile context position */
587 void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext *self)
588 {
589 guint iter_trace, nb_trace;
590
591 LttvTraceContext *tc;
592
593 nb_trace = lttv_traceset_number(self->ts);
594
595 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
596 tc = self->traces[iter_trace];
597 {
598 /* each trace */
599 guint iter_tf, nb_tracefile;
600
601 LttvTracefileContext *tfc;
602
603 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
604 ltt_trace_per_cpu_tracefile_number(tc->t);
605
606 for(iter_tf = 0 ; iter_tf < nb_tracefile ; iter_tf++) {
607 tfc = tc->tracefiles[iter_tf];
608 {
609 /* each tracefile */
610 //ltt_tracefile_copy(tfc->tf_sync_data, tfc->tf);
611 LttEventPosition *ep = ltt_event_position_new();
612
613 ltt_event_position(tfc->e, ep);
614
615 ltt_tracefile_seek_position(tfc->tf, ep);
616 g_free(ep);
617 }
618 }
619 }
620 }
621 }
622
623
624
625 void lttv_process_traceset_begin(LttvTracesetContext *self,
626 LttvHooks *before_traceset,
627 LttvHooks *before_trace,
628 LttvHooks *before_tracefile,
629 LttvHooks *event,
630 LttvHooksById *event_by_id)
631 {
632
633 /* simply add hooks in context. _before hooks are called by add_hooks. */
634 /* It calls all before_traceset, before_trace, and before_tracefile hooks. */
635 lttv_traceset_context_add_hooks(self,
636 before_traceset,
637 before_trace,
638 before_tracefile,
639 event,
640 event_by_id);
641
642 }
643
644 /* Note : a _middle must be preceded from a _seek or another middle */
645 guint lttv_process_traceset_middle(LttvTracesetContext *self,
646 LttTime end,
647 guint nb_events,
648 const LttvTracesetContextPosition *end_position)
649 {
650 GTree *pqueue = self->pqueue;
651
652 guint id;
653
654 LttvTracefileContext *tfc;
655
656 unsigned count = 0;
657
658 gboolean last_ret = FALSE; /* return value of the last hook list called */
659
660 /* Get the next event from the pqueue, call its hooks,
661 reinsert in the pqueue the following event from the same tracefile
662 unless the tracefile is finished or the event is later than the
663 end time. */
664
665 while(TRUE) {
666 tfc = NULL;
667 g_tree_foreach(pqueue, get_first, &tfc);
668 /* End of traceset : tfc is NULL */
669 if(tfc == NULL)
670 {
671 return count;
672 }
673
674 /* Have we reached :
675 * - the maximum number of events specified?
676 * - the end position ?
677 * - the end time ?
678 * then the read is finished. We leave the queue in the same state and
679 * break the loop.
680 */
681
682 if(last_ret == TRUE ||
683 count >= nb_events ||
684 (end_position!=NULL&&lttv_traceset_context_ctx_pos_compare(self,
685 end_position) == 0)||
686 ltt_time_compare(tfc->timestamp, end) >= 0)
687 {
688 return count;
689 }
690
691 /* Get the tracefile with an event for the smallest time found. If two
692 or more tracefiles have events for the same time, hope that lookup
693 and remove are consistent. */
694
695 g_tree_remove(pqueue, tfc);
696 count++;
697
698 id = ltt_event_eventtype_id(tfc->e);
699 last_ret = lttv_hooks_call_merge(tfc->event, tfc,
700 lttv_hooks_by_id_get(tfc->event_by_id, id), tfc);
701
702 if(ltt_tracefile_read(tfc->tf, tfc->e) != NULL) {
703 tfc->timestamp = ltt_event_time(tfc->e);
704 g_tree_insert(pqueue, tfc, tfc);
705 }
706 }
707 }
708
709
710 void lttv_process_traceset_end(LttvTracesetContext *self,
711 LttvHooks *after_traceset,
712 LttvHooks *after_trace,
713 LttvHooks *after_tracefile,
714 LttvHooks *event,
715 LttvHooksById *event_by_id)
716 {
717 /* Remove hooks from context. _after hooks are called by remove_hooks. */
718 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
719 lttv_traceset_context_remove_hooks(self,
720 after_traceset,
721 after_trace,
722 after_tracefile,
723 event,
724 event_by_id);
725 }
726
727 void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
728 {
729 guint i, nb_tracefile;
730
731 LttvTracefileContext *tfc;
732
733 GTree *pqueue = self->ts_context->pqueue;
734
735 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
736 ltt_trace_per_cpu_tracefile_number(self->t);
737
738 for(i = 0 ; i < nb_tracefile ; i++) {
739 tfc = self->tracefiles[i];
740 ltt_tracefile_seek_time(tfc->tf, start);
741 g_tree_remove(pqueue, tfc);
742 if(ltt_tracefile_read(tfc->tf, tfc->e) != NULL) {
743 tfc->timestamp = ltt_event_time(tfc->e);
744 g_tree_insert(pqueue, tfc, tfc);
745 }
746 }
747 }
748
749
750 void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
751 {
752 guint i, nb_trace;
753
754 LttvTraceContext *tc;
755
756 nb_trace = lttv_traceset_number(self->ts);
757 for(i = 0 ; i < nb_trace ; i++) {
758 tc = self->traces[i];
759 lttv_process_trace_seek_time(tc, start);
760 }
761 }
762
763
764 gboolean lttv_process_tracefile_seek_position(LttvTracefileContext *self,
765 const LttEventPosition *pos)
766 {
767 LttvTracefileContext *tfc = self;
768
769 GTree *pqueue = self->t_context->ts_context->pqueue;
770
771 ltt_tracefile_seek_position(tfc->tf, pos);
772 g_tree_remove(pqueue, tfc);
773 if(ltt_tracefile_read(tfc->tf, tfc->e) != NULL) {
774 tfc->timestamp = ltt_event_time(tfc->e);
775 g_tree_insert(pqueue, tfc, tfc);
776 }
777
778 return TRUE;
779 }
780
781 gboolean lttv_process_trace_seek_position(LttvTraceContext *self,
782 const LttvTraceContextPosition *pos)
783 {
784 guint i, nb_tracefile;
785
786 LttvTracefileContext *tfc;
787
788 nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
789 ltt_trace_per_cpu_tracefile_number(self->t);
790
791 if(nb_tracefile != pos->nb_tracefile)
792 return FALSE; /* Error */
793
794 for(i = 0 ; i < nb_tracefile ; i++) {
795 tfc = self->tracefiles[i];
796 lttv_process_tracefile_seek_position(tfc, pos->tf_pos[i]);
797 }
798
799 return TRUE;
800 }
801
802
803
804 gboolean lttv_process_traceset_seek_position(LttvTracesetContext *self,
805 const LttvTracesetContextPosition *pos)
806 {
807 guint i, nb_trace;
808 gboolean sum_ret = TRUE;
809
810 LttvTraceContext *tc;
811
812 nb_trace = lttv_traceset_number(self->ts);
813
814 if(nb_trace != pos->nb_trace)
815 return FALSE; /* Error */
816
817 for(i = 0 ; i < nb_trace ; i++) {
818 tc = self->traces[i];
819 sum_ret = sum_ret && lttv_process_trace_seek_position(tc, &pos->t_pos[i]);
820 }
821
822 return sum_ret;
823 }
824
825
826
827 static LttField *
828 find_field(LttEventType *et, const char *field)
829 {
830 LttType *t;
831
832 LttField *f;
833
834 guint i, nb;
835
836 char *name;
837
838 if(field == NULL) return NULL;
839
840 f = ltt_eventtype_field(et);
841 t = ltt_eventtype_type(et);
842 g_assert(ltt_type_class(t) == LTT_STRUCT);
843 nb = ltt_type_member_number(t);
844 for(i = 0 ; i < nb ; i++) {
845 ltt_type_member_type(t, i, &name);
846 if(strcmp(name, field) == 0) break;
847 }
848 g_assert(i < nb);
849 return ltt_field_member(f, i);
850 }
851
852
853 void
854 lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type,
855 char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th)
856 {
857 LttFacility *f;
858
859 LttEventType *et;
860
861 guint nb, pos;
862
863 nb = ltt_trace_facility_find(t, facility, &pos);
864 if(nb < 1) g_error("No %s facility", facility);
865 f = ltt_trace_facility_get(t, pos);
866 et = ltt_facility_eventtype_get_by_name(f, event_type);
867 if(et == NULL) g_error("Event %s does not exist", event_type);
868
869 th->h = h;
870 th->id = ltt_eventtype_id(et);
871 th->f1 = find_field(et, field1);
872 th->f2 = find_field(et, field2);
873 th->f3 = find_field(et, field3);
874 }
875
876
877 LttvTracesetContextPosition *lttv_traceset_context_position_new()
878 {
879 return g_new(LttvTracesetContextPosition,1);
880 }
881
882
883 void lttv_traceset_context_position_save(const LttvTracesetContext *self,
884 LttvTracesetContextPosition *pos)
885 {
886 guint nb_trace, nb_tracefile;
887 guint iter_trace, iter_tracefile;
888
889 LttvTraceContext *tc;
890
891 LttvTracefileContext *tfc;
892
893 LttEvent *event;
894
895 LttTime timestamp = self->time_span.end_time;
896
897 pos->nb_trace = nb_trace = lttv_traceset_number(self->ts);
898 pos->t_pos = g_new(LttvTraceContextPosition, nb_trace);
899
900 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
901 tc = self->traces[iter_trace];
902 pos->t_pos[iter_trace].nb_tracefile = nb_tracefile =
903 ltt_trace_control_tracefile_number(tc->t) +
904 ltt_trace_per_cpu_tracefile_number(tc->t);
905
906 pos->t_pos[iter_trace].tf_pos = g_new(LttEventPosition*, nb_tracefile);
907 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
908 tfc = tc->tracefiles[iter_tracefile];
909 event = tfc->e;
910 if(event!=NULL) {
911 pos->t_pos[iter_trace].tf_pos[iter_tracefile]
912 = ltt_event_position_new();
913 ltt_event_position(event,
914 pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
915 } else {
916 pos->t_pos[iter_trace].tf_pos[iter_tracefile] = NULL;
917 }
918 if(ltt_time_compare(tfc->timestamp, timestamp) < 0)
919 timestamp = tfc->timestamp;
920 }
921 }
922 pos->timestamp = timestamp;
923 }
924
925 void lttv_traceset_context_position_destroy(LttvTracesetContextPosition *pos)
926 {
927 guint nb_trace;
928 guint iter_trace, iter_tracefile;
929
930 nb_trace = pos->nb_trace;
931
932 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
933 for(iter_tracefile = 0; iter_tracefile <
934 pos->t_pos[iter_trace].nb_tracefile;
935 iter_tracefile++) {
936 if(pos->t_pos[iter_trace].tf_pos[iter_tracefile] != NULL)
937 g_free(pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
938 }
939 g_free(pos->t_pos[iter_trace].tf_pos);
940 }
941 g_free(pos->t_pos);
942
943 }
944
945 void lttv_traceset_context_position_copy(LttvTracesetContextPosition *dest,
946 const LttvTracesetContextPosition *src)
947 {
948 guint nb_trace, nb_tracefile;
949 guint iter_trace, iter_tracefile;
950
951 nb_trace = dest->nb_trace = src->nb_trace;
952 dest->t_pos = g_new(LttvTraceContextPosition, nb_trace);
953
954 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
955
956 nb_tracefile = dest->t_pos[iter_trace].nb_tracefile =
957 src->t_pos[iter_trace].nb_tracefile;
958
959 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
960 dest->t_pos[iter_trace].tf_pos[iter_tracefile] =
961 ltt_event_position_new();
962 if(src->t_pos[iter_trace].tf_pos[iter_tracefile] != NULL)
963 ltt_event_position_copy(
964 dest->t_pos[iter_trace].tf_pos[iter_tracefile],
965 src->t_pos[iter_trace].tf_pos[iter_tracefile]);
966 else
967 dest->t_pos[iter_trace].tf_pos[iter_tracefile] = NULL;
968 }
969 }
970
971 dest->timestamp = src->timestamp;
972 }
973
974 gint lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext *self,
975 const LttvTracesetContextPosition *pos)
976 {
977 guint nb_trace, nb_tracefile;
978 guint iter_trace, iter_tracefile;
979 gint ret;
980
981 LttvTraceContext *tc;
982
983 LttvTracefileContext *tfc;
984
985 LttEvent *event;
986
987 nb_trace = lttv_traceset_number(self->ts);
988
989 if(pos->nb_trace != nb_trace)
990 g_error("lttv_traceset_context_ctx_pos_compare : nb_trace does not match.");
991
992 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
993 tc = self->traces[iter_trace];
994 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
995 ltt_trace_per_cpu_tracefile_number(tc->t);
996
997 if(pos->t_pos[iter_trace].nb_tracefile != nb_tracefile)
998 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
999
1000 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
1001 tfc = tc->tracefiles[iter_tracefile];
1002 event = tfc->e;
1003 ret = ltt_event_event_position_compare(event,
1004 pos->t_pos[iter_trace].tf_pos[iter_tracefile]);
1005 if(ret != 0)
1006 return ret;
1007 }
1008 }
1009 return 0;
1010 }
1011
1012
1013 gint lttv_traceset_context_pos_pos_compare(
1014 const LttvTracesetContextPosition *pos1,
1015 const LttvTracesetContextPosition *pos2)
1016 {
1017 guint nb_trace, nb_tracefile;
1018 guint iter_trace, iter_tracefile;
1019
1020 gint ret;
1021
1022 nb_trace = pos1->nb_trace;
1023 if(nb_trace != pos2->nb_trace)
1024 g_error("lttv_traceset_context_pos_pos_compare : nb_trace does not match.");
1025
1026 for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) {
1027
1028 nb_tracefile = pos1->t_pos[iter_trace].nb_tracefile;
1029 if(nb_tracefile != pos2->t_pos[iter_trace].nb_tracefile)
1030 g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match.");
1031
1032 for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) {
1033 ret = ltt_event_position_compare(
1034 pos1->t_pos[iter_trace].tf_pos[iter_tracefile],
1035 pos2->t_pos[iter_trace].tf_pos[iter_tracefile]);
1036 if(ret != 0)
1037 return ret;
1038 }
1039 }
1040 return 0;
1041 }
1042
1043
1044 LttTime lttv_traceset_context_position_get_time(
1045 const LttvTracesetContextPosition *pos)
1046 {
1047 return pos->timestamp;
1048 }
1049
1050
1051 LttvTracefileContext *lttv_traceset_context_get_current_tfc(LttvTracesetContext *self)
1052 {
1053 GTree *pqueue = self->pqueue;
1054 LttvTracefileContext *tfc = NULL;
1055
1056 g_tree_foreach(pqueue, get_first, &tfc);
1057
1058 return tfc;
1059 }
This page took 0.052341 seconds and 4 git commands to generate.