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