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