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