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