fix note reserving byte order in calc_nsec_per_cycle
[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 }
698e81c2 51 } else {
52 comparison = 0;
cf94ff67 53 }
698e81c2 54
cf94ff67 55 return comparison;
8697a616 56}
57
8697a616 58struct _LttvTracesetContextPosition {
27304273 59 GArray *ep; /* Array of LttEventPosition */
60 GArray *tfc; /* Array of corresponding
61 TracefileContext* */
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{
9d239bd9 391 guint i, index;
8697a616 392
393 LttvHooks *hook;
394
395 lttv_hooks_call(before_tracefile, self);
396 lttv_hooks_add_list(self->event, event);
9d239bd9 397 if(event_by_id != NULL) {
398 for(i = 0; i < event_by_id->array->len; i++) {
399 index = g_array_index(event_by_id->array, guint, i);
400 hook = lttv_hooks_by_id_find(self->event_by_id, index);
401 lttv_hooks_add_list(hook, lttv_hooks_by_id_get(event_by_id, index));
8697a616 402 }
9d239bd9 403 }
a8c0f09d 404}
405
8697a616 406void lttv_tracefile_context_remove_hooks(LttvTracefileContext *self,
407 LttvHooks *after_tracefile,
408 LttvHooks *event,
409 LttvHooksById *event_by_id)
a8c0f09d 410{
9d239bd9 411 guint i, index;
8697a616 412
413 LttvHooks *hook;
414
8697a616 415 lttv_hooks_remove_list(self->event, event);
9d239bd9 416 if(event_by_id != NULL) {
417 for(i = 0; i < event_by_id->array->len; i++) {
418 index = g_array_index(event_by_id->array, guint, i);
419 hook = lttv_hooks_by_id_get(self->event_by_id, index);
41a9e0c3 420 if(hook != NULL)
9d239bd9 421 lttv_hooks_remove_list(hook, lttv_hooks_by_id_get(event_by_id, index));
8697a616 422 }
9d239bd9 423 }
8697a616 424
425 lttv_hooks_call(after_tracefile, self);
a8c0f09d 426}
427
8697a616 428
429
a8c0f09d 430void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc,
431 unsigned i,
8697a616 432 LttvHooks *event_by_id)
a8c0f09d 433{
434 LttvHooks * h;
8697a616 435 h = lttv_hooks_by_id_find(tfc->event_by_id, i);
436 lttv_hooks_add_list(h, event_by_id);
a8c0f09d 437}
438
439void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc,
440 unsigned i)
441{
8697a616 442 lttv_hooks_by_id_remove(tfc->event_by_id, i);
a8c0f09d 443}
dc877563 444
ba576a78 445static LttvTracesetContext *
dc877563 446new_traceset_context(LttvTracesetContext *self)
447{
ffd54a90 448 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
dc877563 449}
450
451
ba576a78 452static LttvTraceContext *
dc877563 453new_trace_context(LttvTracesetContext *self)
454{
ffd54a90 455 return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
dc877563 456}
457
458
ba576a78 459static LttvTracefileContext *
dc877563 460new_tracefile_context(LttvTracesetContext *self)
461{
ffd54a90 462 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
dc877563 463}
464
465
466static void
467traceset_context_instance_init (GTypeInstance *instance, gpointer g_class)
468{
469 /* Be careful of anything which would not work well with shallow copies */
470}
471
472
473static void
474traceset_context_finalize (LttvTracesetContext *self)
475{
b445142a 476 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
477 ->finalize(G_OBJECT(self));
dc877563 478}
479
480
481static void
482traceset_context_class_init (LttvTracesetContextClass *klass)
483{
484 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
485
ffd54a90 486 gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
dc877563 487 klass->init = init;
488 klass->fini = fini;
489 klass->new_traceset_context = new_traceset_context;
490 klass->new_trace_context = new_trace_context;
491 klass->new_tracefile_context = new_tracefile_context;
492}
493
494
495GType
ffd54a90 496lttv_traceset_context_get_type(void)
dc877563 497{
498 static GType type = 0;
499 if (type == 0) {
500 static const GTypeInfo info = {
ffd54a90 501 sizeof (LttvTracesetContextClass),
dc877563 502 NULL, /* base_init */
503 NULL, /* base_finalize */
ffd54a90 504 (GClassInitFunc) traceset_context_class_init, /* class_init */
dc877563 505 NULL, /* class_finalize */
506 NULL, /* class_data */
ffd54a90 507 sizeof (LttvTracesetContext),
dc877563 508 0, /* n_preallocs */
00e74b69 509 (GInstanceInitFunc) traceset_context_instance_init, /* instance_init */
510 NULL /* Value handling */
dc877563 511 };
512
ffd54a90 513 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
dc877563 514 &info, 0);
515 }
516 return type;
517}
518
519
520static void
521trace_context_instance_init (GTypeInstance *instance, gpointer g_class)
522{
523 /* Be careful of anything which would not work well with shallow copies */
524}
525
526
527static void
528trace_context_finalize (LttvTraceContext *self)
529{
b445142a 530 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
531 finalize(G_OBJECT(self));
dc877563 532}
533
534
535static void
536trace_context_class_init (LttvTraceContextClass *klass)
537{
538 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
539
ffd54a90 540 gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
dc877563 541}
542
543
544GType
ffd54a90 545lttv_trace_context_get_type(void)
dc877563 546{
547 static GType type = 0;
548 if (type == 0) {
549 static const GTypeInfo info = {
ffd54a90 550 sizeof (LttvTraceContextClass),
dc877563 551 NULL, /* base_init */
552 NULL, /* base_finalize */
ffd54a90 553 (GClassInitFunc) trace_context_class_init, /* class_init */
dc877563 554 NULL, /* class_finalize */
555 NULL, /* class_data */
c6bc9cb9 556 sizeof (LttvTraceContext),
dc877563 557 0, /* n_preallocs */
00e74b69 558 (GInstanceInitFunc) trace_context_instance_init, /* instance_init */
559 NULL /* Value handling */
dc877563 560 };
561
ffd54a90 562 type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
dc877563 563 &info, 0);
564 }
565 return type;
566}
567
568
569static void
570tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class)
571{
572 /* Be careful of anything which would not work well with shallow copies */
573}
574
575
576static void
577tracefile_context_finalize (LttvTracefileContext *self)
578{
b445142a 579 G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
580 ->finalize(G_OBJECT(self));
dc877563 581}
582
583
584static void
585tracefile_context_class_init (LttvTracefileContextClass *klass)
586{
587 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
588
ffd54a90 589 gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
590}
591
592
593GType
594lttv_tracefile_context_get_type(void)
595{
596 static GType type = 0;
597 if (type == 0) {
598 static const GTypeInfo info = {
599 sizeof (LttvTracefileContextClass),
600 NULL, /* base_init */
601 NULL, /* base_finalize */
602 (GClassInitFunc) tracefile_context_class_init, /* class_init */
603 NULL, /* class_finalize */
604 NULL, /* class_data */
605 sizeof (LttvTracefileContext),
606 0, /* n_preallocs */
00e74b69 607 (GInstanceInitFunc) tracefile_context_instance_init, /* instance_init */
608 NULL /* Value handling */
ffd54a90 609 };
610
611 type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType",
612 &info, 0);
613 }
614 return type;
dc877563 615}
616
617
dc877563 618
6843100a 619static gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
dc877563 620 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
621 return TRUE;
622}
623
698e81c2 624static gboolean test_tree(gpointer key, gpointer value, gpointer user_data) {
625
626 g_assert(((LttvTracefileContext *)user_data) != (LttvTracefileContext *)value);
627 return FALSE;
628}
629
630
dc877563 631
8697a616 632void lttv_process_traceset_begin(LttvTracesetContext *self,
633 LttvHooks *before_traceset,
634 LttvHooks *before_trace,
635 LttvHooks *before_tracefile,
636 LttvHooks *event,
637 LttvHooksById *event_by_id)
638{
dc877563 639
8697a616 640 /* simply add hooks in context. _before hooks are called by add_hooks. */
641 /* It calls all before_traceset, before_trace, and before_tracefile hooks. */
642 lttv_traceset_context_add_hooks(self,
643 before_traceset,
644 before_trace,
645 before_tracefile,
646 event,
647 event_by_id);
648
2a2fa4f0 649}
650
8697a616 651/* Note : a _middle must be preceded from a _seek or another middle */
652guint lttv_process_traceset_middle(LttvTracesetContext *self,
653 LttTime end,
b8eccacd 654 guint nb_events,
8697a616 655 const LttvTracesetContextPosition *end_position)
2a2fa4f0 656{
657 GTree *pqueue = self->pqueue;
658
698e81c2 659 guint fac_id, ev_id, id;
2a2fa4f0 660
2a2fa4f0 661 LttvTracefileContext *tfc;
662
eed2ef37 663 LttEvent *e;
664
2a2fa4f0 665 unsigned count = 0;
666
698e81c2 667 guint read_ret = FALSE;
668
a54f091a 669 gboolean last_ret = FALSE; /* return value of the last hook list called */
670
dc877563 671 /* Get the next event from the pqueue, call its hooks,
672 reinsert in the pqueue the following event from the same tracefile
673 unless the tracefile is finished or the event is later than the
8697a616 674 end time. */
dc877563 675
ffd54a90 676 while(TRUE) {
dc877563 677 tfc = NULL;
678 g_tree_foreach(pqueue, get_first, &tfc);
33f7a12c 679 /* End of traceset : tfc is NULL */
1d1df11d 680 if(unlikely(tfc == NULL))
a43d67ba 681 {
a43d67ba 682 return count;
683 }
dc877563 684
8697a616 685 /* Have we reached :
686 * - the maximum number of events specified?
687 * - the end position ?
688 * - the end time ?
689 * then the read is finished. We leave the queue in the same state and
690 * break the loop.
691 */
692
1d1df11d 693 if(unlikely(last_ret == TRUE ||
d052ffc3 694 ((count >= nb_events) && (nb_events != G_MAXULONG)) ||
8b0bbe19 695 (end_position!=NULL&&lttv_traceset_context_ctx_pos_compare(self,
696 end_position) == 0)||
1d1df11d 697 ltt_time_compare(end, tfc->timestamp) <= 0))
a43d67ba 698 {
a43d67ba 699 return count;
700 }
2a2fa4f0 701
308711e5 702 /* Get the tracefile with an event for the smallest time found. If two
703 or more tracefiles have events for the same time, hope that lookup
704 and remove are consistent. */
698e81c2 705
f95bc830 706 g_tree_remove(pqueue, tfc);
698e81c2 707
708 g_tree_foreach(pqueue, test_tree, tfc);
2a2fa4f0 709 count++;
eed2ef37 710
711 e = ltt_tracefile_get_event(tfc->tf);
698e81c2 712 fac_id = ltt_event_facility_id(e);
713 ev_id = ltt_event_eventtype_id(e);
714 id = GET_HOOK_ID(fac_id, ev_id);
a54f091a 715 last_ret = lttv_hooks_call_merge(tfc->event, tfc,
8697a616 716 lttv_hooks_by_id_get(tfc->event_by_id, id), tfc);
dc877563 717
698e81c2 718 read_ret = ltt_tracefile_read(tfc->tf);
719
720 if(likely(!read_ret)) {
721 g_debug("got someting");
eed2ef37 722 tfc->timestamp = ltt_event_time(e);
33f7a12c 723 g_tree_insert(pqueue, tfc, tfc);
698e81c2 724 } else {
725 if(read_ret == ERANGE)
726 g_debug("End of trace");
727 else
728 g_error("Error happened in lttv_process_traceset_middle");
dc877563 729 }
730 }
2a2fa4f0 731}
732
733
8697a616 734void lttv_process_traceset_end(LttvTracesetContext *self,
735 LttvHooks *after_traceset,
736 LttvHooks *after_trace,
737 LttvHooks *after_tracefile,
738 LttvHooks *event,
739 LttvHooksById *event_by_id)
2a2fa4f0 740{
8697a616 741 /* Remove hooks from context. _after hooks are called by remove_hooks. */
742 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
743 lttv_traceset_context_remove_hooks(self,
744 after_traceset,
745 after_trace,
746 after_tracefile,
747 event,
748 event_by_id);
749}
2a2fa4f0 750
27304273 751/* Subtile modification :
752 * if tracefile has no event at or after the time requested, it is not put in
753 * the queue, as the next read would fail. */
8697a616 754void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
755{
756 guint i, nb_tracefile;
2a2fa4f0 757
eed2ef37 758 gint ret;
759
2a2fa4f0 760 LttvTracefileContext *tfc;
761
a5ba1787 762 GTree *pqueue = self->ts_context->pqueue;
763
eed2ef37 764 nb_tracefile = self->tracefiles->len;
dc877563 765
8697a616 766 for(i = 0 ; i < nb_tracefile ; i++) {
3865ea09 767 tfc = g_array_index(self->tracefiles, LttvTracefileContext*, i);
eed2ef37 768 ret = ltt_tracefile_seek_time(tfc->tf, start);
27304273 769 if(ret == EPERM) g_error("error in lttv_process_trace_seek_time seek");
a5ba1787 770 g_tree_remove(pqueue, tfc);
27304273 771
772 if(ret == 0) { /* not ERANGE especially */
773 tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf));
774 g_tree_insert(pqueue, tfc, tfc);
775 }
8697a616 776 }
777}
dc877563 778
2a2fa4f0 779
8697a616 780void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
781{
782 guint i, nb_trace;
2a2fa4f0 783
8697a616 784 LttvTraceContext *tc;
2a2fa4f0 785
8697a616 786 nb_trace = lttv_traceset_number(self->ts);
787 for(i = 0 ; i < nb_trace ; i++) {
788 tc = self->traces[i];
789 lttv_process_trace_seek_time(tc, start);
790 }
dc877563 791}
b445142a 792
308711e5 793
8697a616 794gboolean lttv_process_traceset_seek_position(LttvTracesetContext *self,
795 const LttvTracesetContextPosition *pos)
308711e5 796{
27304273 797 guint i;
308711e5 798 LttvTraceContext *tc;
27304273 799 LttvTracefileContext *tfc;
308711e5 800
27304273 801 g_tree_destroy(self->pqueue);
802 self->pqueue = g_tree_new(compare_tracefile);
8697a616 803
27304273 804 for(i=0;i<pos->ep->len; i++) {
805 LttEventPosition *ep = g_array_index(pos->ep, LttEventPosition*, i);
806 LttvTracefileContext *tfc =
807 g_array_index(pos->tfc, LttvTracefileContext*, i);
808 g_assert(ltt_tracefile_seek_position(tfc->tf, ep) == 0);
809 tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf));
810 g_tree_insert(self->pqueue, tfc, tfc);
308711e5 811 }
27304273 812 return TRUE;
308711e5 813}
814
815
8697a616 816
b445142a 817static LttField *
eed2ef37 818find_field(LttEventType *et, const GQuark field)
b445142a 819{
820 LttType *t;
821
822 LttField *f;
823
824 guint i, nb;
825
eed2ef37 826 GQuark name;
b445142a 827
eed2ef37 828 /* Field is unset */
829 if(field == 0) return NULL;
830
b445142a 831 f = ltt_eventtype_field(et);
832 t = ltt_eventtype_type(et);
833 g_assert(ltt_type_class(t) == LTT_STRUCT);
834 nb = ltt_type_member_number(t);
835 for(i = 0 ; i < nb ; i++) {
836 ltt_type_member_type(t, i, &name);
eed2ef37 837 if(name == field) break;
b445142a 838 }
839 g_assert(i < nb);
840 return ltt_field_member(f, i);
841}
842
eed2ef37 843LttvTraceHookByFacility *lttv_trace_hook_get_fac(LttvTraceHook *th,
844 guint facility_id)
845{
846 return &g_array_index(th->fac_index, LttvTraceHookByFacility, facility_id);
847}
848
849/* Get the first facility corresponding to the name. As the types must be
850 * compatible, it is relevant to use the field name and sizes of the first
851 * facility to create data structures and assume the data will be compatible
852 * thorough the trace */
853LttvTraceHookByFacility *lttv_trace_hook_get_first(LttvTraceHook *th)
854{
855 g_assert(th->fac_list->len > 0);
856 return g_array_index(th->fac_list, LttvTraceHookByFacility*, 0);
857}
858
b445142a 859
eed2ef37 860/* Returns 0 on success, -1 if fails. */
861gint
862lttv_trace_find_hook(LttTrace *t, GQuark facility, GQuark event,
863 GQuark field1, GQuark field2, GQuark field3, LttvHook h, LttvTraceHook *th)
b445142a 864{
865 LttFacility *f;
866
eed2ef37 867 LttEventType *et, *first_et;
868
869 GArray *facilities;
870
d052ffc3 871 guint i, fac_id, ev_id;
b445142a 872
eed2ef37 873 LttvTraceHookByFacility *thf, *first_thf;
b445142a 874
eed2ef37 875 facilities = ltt_trace_facility_get_by_name(t, facility);
876
877 if(unlikely(facilities == NULL)) goto facility_error;
878
879 th->fac_index = g_array_sized_new(FALSE, TRUE,
880 sizeof(LttvTraceHookByFacility),
881 NUM_FACILITIES);
882 th->fac_index = g_array_set_size(th->fac_index, NUM_FACILITIES);
b445142a 883
eed2ef37 884 th->fac_list = g_array_sized_new(FALSE, TRUE,
885 sizeof(LttvTraceHookByFacility*),
886 facilities->len);
887 th->fac_list = g_array_set_size(th->fac_list, facilities->len);
888
889 fac_id = g_array_index(facilities, guint, 0);
890 f = ltt_trace_get_facility_by_num(t, fac_id);
891
cb03932a 892 et = ltt_facility_eventtype_get_by_name(f, event);
eed2ef37 893 if(unlikely(et == NULL)) goto event_error;
894
895 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
896 g_array_index(th->fac_list, LttvTraceHookByFacility*, 0)
897 = thf;
9d239bd9 898
d052ffc3 899 ev_id = ltt_eventtype_id(et);
900
eed2ef37 901 thf->h = h;
d052ffc3 902 thf->id = GET_HOOK_ID(fac_id, ev_id);
eed2ef37 903 thf->f1 = find_field(et, field1);
904 thf->f2 = find_field(et, field2);
905 thf->f3 = find_field(et, field3);
906
907 first_thf = thf;
908
909 /* Check for type compatibility too */
910 for(i=1;i<facilities->len;i++) {
911 fac_id = g_array_index(facilities, guint, i);
912 f = ltt_trace_get_facility_by_num(t, fac_id);
913
914 et = ltt_facility_eventtype_get_by_name(f, ltt_eventtype_name(et));
915 if(unlikely(et == NULL)) goto event_error;
916
917 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
918 g_array_index(th->fac_list, LttvTraceHookByFacility*, i)
919 = thf;
d052ffc3 920 ev_id = ltt_eventtype_id(et);
eed2ef37 921 thf->h = h;
d052ffc3 922 thf->id = GET_HOOK_ID(fac_id, ev_id);
eed2ef37 923 thf->f1 = find_field(et, field1);
924 if(check_fields_compatibility(first_et, et,
925 first_thf->f1, thf->f1))
926 goto type_error;
927
928 thf->f2 = find_field(et, field2);
929 if(check_fields_compatibility(first_et, et,
930 first_thf->f2, thf->f2))
931 goto type_error;
932
933 thf->f3 = find_field(et, field3);
934 if(check_fields_compatibility(first_et, et,
935 first_thf->f3, thf->f3))
936 goto type_error;
937 }
938
939 return 0;
940
941type_error:
942 goto free;
943event_error:
944 g_error("Event type %s does not exist",
945 g_quark_to_string(ltt_eventtype_name(et)));
946 goto free;
947facility_error:
948 g_error("No %s facility", g_quark_to_string(facility));
949 goto free;
950free:
951 g_array_free(th->fac_index, TRUE);
952 g_array_free(th->fac_list, TRUE);
953 th->fac_index = NULL;
954 th->fac_list = NULL;
955 return -1;
956}
957
958void lttv_trace_hook_destroy(LttvTraceHook *th)
959{
960 g_array_free(th->fac_index, TRUE);
961 g_array_free(th->fac_list, TRUE);
b445142a 962}
963
964
8b0bbe19 965LttvTracesetContextPosition *lttv_traceset_context_position_new()
5e2c04a2 966{
27304273 967 LttvTracesetContextPosition *pos = g_new(LttvTracesetContextPosition,1);
968 pos->ep = g_array_sized_new(FALSE, TRUE, sizeof(LttEventPosition*),
969 10);
970 pos->tfc = g_array_sized_new(FALSE, TRUE, sizeof(LttvTracefileContext*),
971 10);
972 pos->timestamp = ltt_time_infinite;
973 return pos;
5e2c04a2 974}
975
27304273 976gboolean traverse_get_tfc(gpointer key, gpointer value, gpointer data)
8697a616 977{
27304273 978 LttvTracefileContext *tfc = (LttvTracefileContext *)value;
979 LttvTracesetContextPosition *pos = (LttvTracesetContextPosition *)data;
8697a616 980
27304273 981 LttEvent *event = ltt_tracefile_get_event(tfc->tf);
982 LttEventPosition *ep = ltt_event_position_new();
983
984 ltt_event_position(event, ep);
8697a616 985
27304273 986 g_array_append_val(pos->ep, ep);
987 g_array_append_val(pos->tfc, tfc);
2d262115 988
27304273 989 if(ltt_time_compare(tfc->timestamp, pos->timestamp) < 0)
990 pos->timestamp = tfc->timestamp;
8697a616 991
27304273 992 return 0;
993}
8697a616 994
27304273 995/* Subtile modification :
996 * only save the tracefiles that are loaded in the pqueue */
997void lttv_traceset_context_position_save(const LttvTracesetContext *self,
998 LttvTracesetContextPosition *pos)
999{
1000 g_tree_foreach(self->pqueue, traverse_get_tfc, pos);
8697a616 1001}
1002
1003void lttv_traceset_context_position_destroy(LttvTracesetContextPosition *pos)
1004{
27304273 1005 int i;
1006 for(i=0;i<pos->ep->len;i++)
1007 g_free(g_array_index(pos->ep, LttEventPosition*, i));
1008 g_array_free(pos->ep, TRUE);
1009 g_array_free(pos->tfc, TRUE);
1010 g_free(pos);
8697a616 1011}
1012
5e2c04a2 1013void lttv_traceset_context_position_copy(LttvTracesetContextPosition *dest,
1014 const LttvTracesetContextPosition *src)
1015{
27304273 1016 int i;
5e2c04a2 1017
27304273 1018 g_array_set_size(dest->ep, src->ep->len);
1019 g_array_set_size(dest->tfc, src->tfc->len);
1020
1021 for(i=0;i<src->ep->len;i++) {
1022 g_array_index(dest->ep, LttEventPosition*, i) = ltt_event_position_new();
1023 ltt_event_position_copy(
1024 g_array_index(dest->ep, LttEventPosition*, i),
1025 g_array_index(src->ep, LttEventPosition*, i));
1026 }
1027 for(i=0;i<src->tfc->len;i++) {
1028 g_array_index(dest->tfc, LttvTracefileContext*, i) =
1029 g_array_index(src->tfc, LttvTracefileContext*, i);
5e2c04a2 1030 }
5e2c04a2 1031 dest->timestamp = src->timestamp;
1032}
1033
8697a616 1034gint lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext *self,
1035 const LttvTracesetContextPosition *pos)
1036{
27304273 1037 int i;
1038 int ret;
8697a616 1039
27304273 1040 for(i=0;i<pos->ep->len;i++) {
1041 LttEventPosition *ep = g_array_index(pos->ep, LttEventPosition*, i);
1042 LttvTracefileContext *tfc =
1043 g_array_index(pos->tfc, LttvTracefileContext*, i);
8697a616 1044
27304273 1045 LttEvent *event = ltt_tracefile_get_event(tfc->tf);
8697a616 1046
27304273 1047 ret = ltt_event_position_compare((LttEventPosition*)event,
1048 ep);
1049 if(ret != 0) return ret;
8697a616 1050
8697a616 1051 }
1052 return 0;
1053}
1054
1055
1056gint lttv_traceset_context_pos_pos_compare(
1057 const LttvTracesetContextPosition *pos1,
1058 const LttvTracesetContextPosition *pos2)
1059{
27304273 1060 int i, j;
1061 int ret;
8697a616 1062
27304273 1063 for(i=0;i<pos1->ep->len;i++) {
1064 LttEventPosition *ep1 = g_array_index(pos1->ep, LttEventPosition*, i);
1065 LttTracefile *tf1 = ltt_event_position_tracefile(ep1);
1066
1067 for(j=0;j<pos2->ep->len;j++) {
1068 LttEventPosition *ep2 = g_array_index(pos2->ep, LttEventPosition*, j);
1069 LttTracefile *tf2 = ltt_event_position_tracefile(ep2);
8697a616 1070
27304273 1071 if(tf1 == tf2) {
1072 ret = ltt_event_position_compare(ep1, ep2);
1073 if(ret != 0) return ret;
1074 }
8697a616 1075 }
1076 }
1077 return 0;
27304273 1078
8697a616 1079}
1080
1081
2d262115 1082LttTime lttv_traceset_context_position_get_time(
1083 const LttvTracesetContextPosition *pos)
1084{
1085 return pos->timestamp;
1086}
1087
1088
1089LttvTracefileContext *lttv_traceset_context_get_current_tfc(LttvTracesetContext *self)
1090{
1091 GTree *pqueue = self->pqueue;
b56b5fec 1092 LttvTracefileContext *tfc = NULL;
2d262115 1093
1094 g_tree_foreach(pqueue, get_first, &tfc);
1095
1096 return tfc;
1097}
This page took 0.086607 seconds and 4 git commands to generate.