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