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