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