fix seek time
[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)) {
8fe3c6b6 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{
327a4314 168 guint i, nb_trace;
dc877563 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);
79257ba5 181 // self->sync_position = lttv_traceset_context_position_new();
dc877563 182 for(i = 0 ; i < nb_trace ; i++) {
ffd54a90 183 tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
dc877563 184 self->traces[i] = tc;
185
186 tc->ts_context = self;
187 tc->index = i;
308711e5 188 tc->vt = lttv_traceset_get(ts, i);
189 tc->t = lttv_trace(tc->vt);
ffd54a90 190 tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
308711e5 191 tc->t_a = lttv_trace_attribute(tc->vt);
3865ea09 192 tc->tracefiles = g_array_sized_new(FALSE, TRUE,
193 sizeof(LttvTracefileContext*), 10);
eed2ef37 194
195 tracefiles_groups = ltt_trace_get_tracefiles_groups(tc->t);
e45551ac 196 if(tracefiles_groups != NULL) {
197 args.func = (ForEachTraceFileFunc)init_tracefile_context;
198 args.func_args = tc;
eed2ef37 199
e45551ac 200 g_datalist_foreach(tracefiles_groups,
201 (GDataForeachFunc)compute_tracefile_group,
202 &args);
203 }
eed2ef37 204
205#if 0
dc877563 206 nb_control = ltt_trace_control_tracefile_number(tc->t);
207 nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t);
208 nb_tracefile = nb_control + nb_per_cpu;
dbb7bb09 209 tc->tracefiles = g_new(LttvTracefileContext *, nb_tracefile);
dc877563 210
211 for(j = 0 ; j < nb_tracefile ; j++) {
ffd54a90 212 tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
dbb7bb09 213 tc->tracefiles[j] = tfc;
214 tfc->index = j;
215
dc877563 216 if(j < nb_control) {
dc877563 217 tfc->control = TRUE;
ffd54a90 218 tfc->tf = ltt_trace_control_tracefile_get(tc->t, j);
dc877563 219 }
220 else {
dc877563 221 tfc->control = FALSE;
ffd54a90 222 tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control);
dc877563 223 }
eed2ef37 224
dc877563 225 tfc->t_context = tc;
d3e01c7a 226 tfc->e = ltt_event_new();
8697a616 227 tfc->event = lttv_hooks_new();
228 tfc->event_by_id = lttv_hooks_by_id_new();
ffd54a90 229 tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
dc877563 230 }
eed2ef37 231#endif //0
232
dc877563 233 }
2d262115 234 self->pqueue = g_tree_new(compare_tracefile);
eed2ef37 235 lttv_process_traceset_seek_time(self, ltt_time_zero);
33f7a12c 236 lttv_traceset_context_compute_time_span(self, &self->time_span);
8697a616 237
dc877563 238}
239
240
241void fini(LttvTracesetContext *self)
242{
dbb7bb09 243 guint i, j, nb_trace, nb_tracefile;
dc877563 244
245 LttvTraceContext *tc;
246
1986f254 247 LttvTracefileContext **tfc;
dc877563 248
ffd54a90 249 LttvTraceset *ts = self->ts;
dc877563 250
8697a616 251 g_tree_destroy(self->pqueue);
2061e03d 252 g_object_unref(self->a);
79257ba5 253 // lttv_traceset_context_position_destroy(self->sync_position);
dc877563 254
255 nb_trace = lttv_traceset_number(ts);
256
257 for(i = 0 ; i < nb_trace ; i++) {
258 tc = self->traces[i];
259
ffd54a90 260 g_object_unref(tc->a);
dc877563 261
eed2ef37 262 nb_tracefile = tc->tracefiles->len;
dc877563 263
264 for(j = 0 ; j < nb_tracefile ; j++) {
1986f254 265 tfc = &g_array_index(tc->tracefiles, LttvTracefileContext*, j);
266 lttv_hooks_destroy((*tfc)->event);
267 lttv_hooks_by_id_destroy((*tfc)->event_by_id);
268 g_object_unref((*tfc)->a);
269 g_object_unref(*tfc);
dc877563 270 }
eed2ef37 271 g_array_free(tc->tracefiles, TRUE);
dc877563 272 g_object_unref(tc);
273 }
274 g_free(self->traces);
275}
276
277
278void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
8697a616 279 LttvHooks *before_traceset,
dc877563 280 LttvHooks *before_trace,
ffd54a90 281 LttvHooks *before_tracefile,
8697a616 282 LttvHooks *event,
283 LttvHooksById *event_by_id)
dc877563 284{
285 LttvTraceset *ts = self->ts;
286
8697a616 287 guint i, nb_trace;
dc877563 288
289 LttvTraceContext *tc;
290
8697a616 291 lttv_hooks_call(before_traceset, self);
dc877563 292
dc877563 293 nb_trace = lttv_traceset_number(ts);
294
295 for(i = 0 ; i < nb_trace ; i++) {
296 tc = self->traces[i];
8697a616 297 lttv_trace_context_add_hooks(tc,
298 before_trace,
299 before_tracefile,
300 event,
301 event_by_id);
dc877563 302 }
303}
304
305
306void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
dc877563 307 LttvHooks *after_traceset,
dc877563 308 LttvHooks *after_trace,
ffd54a90 309 LttvHooks *after_tracefile,
8697a616 310 LttvHooks *event,
311 LttvHooksById *event_by_id)
dc877563 312{
8697a616 313
dc877563 314 LttvTraceset *ts = self->ts;
315
8697a616 316 guint i, nb_trace;
dc877563 317
318 LttvTraceContext *tc;
319
dc877563 320 nb_trace = lttv_traceset_number(ts);
321
322 for(i = 0 ; i < nb_trace ; i++) {
323 tc = self->traces[i];
8697a616 324 lttv_trace_context_remove_hooks(tc,
325 after_trace,
326 after_tracefile,
327 event,
328 event_by_id);
dc877563 329 }
8697a616 330
331 lttv_hooks_call(after_traceset, self);
332
333
dc877563 334}
335
8697a616 336void lttv_trace_context_add_hooks(LttvTraceContext *self,
337 LttvHooks *before_trace,
338 LttvHooks *before_tracefile,
339 LttvHooks *event,
340 LttvHooksById *event_by_id)
a8c0f09d 341{
8697a616 342 guint i, nb_tracefile;
343
1986f254 344 LttvTracefileContext **tfc;
8697a616 345
346 lttv_hooks_call(before_trace, self);
eed2ef37 347
348 nb_tracefile = self->tracefiles->len;
8697a616 349
350 for(i = 0 ; i < nb_tracefile ; i++) {
1986f254 351 tfc = &g_array_index(self->tracefiles, LttvTracefileContext*, i);
352 lttv_tracefile_context_add_hooks(*tfc,
8697a616 353 before_tracefile,
354 event,
355 event_by_id);
356 }
a8c0f09d 357}
358
8697a616 359
360
361void lttv_trace_context_remove_hooks(LttvTraceContext *self,
362 LttvHooks *after_trace,
363 LttvHooks *after_tracefile,
364 LttvHooks *event,
365 LttvHooksById *event_by_id)
a8c0f09d 366{
8697a616 367 guint i, nb_tracefile;
368
1986f254 369 LttvTracefileContext **tfc;
8697a616 370
eed2ef37 371 nb_tracefile = self->tracefiles->len;
8697a616 372
373 for(i = 0 ; i < nb_tracefile ; i++) {
1986f254 374 tfc = &g_array_index(self->tracefiles, LttvTracefileContext*, i);
375 lttv_tracefile_context_remove_hooks(*tfc,
8697a616 376 after_tracefile,
377 event,
378 event_by_id);
379 }
380
381 lttv_hooks_call(after_trace, self);
a8c0f09d 382}
383
8697a616 384void lttv_tracefile_context_add_hooks(LttvTracefileContext *self,
385 LttvHooks *before_tracefile,
386 LttvHooks *event,
387 LttvHooksById *event_by_id)
a8c0f09d 388{
9d239bd9 389 guint i, index;
8697a616 390
391 LttvHooks *hook;
392
393 lttv_hooks_call(before_tracefile, self);
394 lttv_hooks_add_list(self->event, event);
9d239bd9 395 if(event_by_id != NULL) {
396 for(i = 0; i < event_by_id->array->len; i++) {
397 index = g_array_index(event_by_id->array, guint, i);
398 hook = lttv_hooks_by_id_find(self->event_by_id, index);
399 lttv_hooks_add_list(hook, lttv_hooks_by_id_get(event_by_id, index));
8697a616 400 }
9d239bd9 401 }
a8c0f09d 402}
403
8697a616 404void lttv_tracefile_context_remove_hooks(LttvTracefileContext *self,
405 LttvHooks *after_tracefile,
406 LttvHooks *event,
407 LttvHooksById *event_by_id)
a8c0f09d 408{
9d239bd9 409 guint i, index;
8697a616 410
411 LttvHooks *hook;
412
8697a616 413 lttv_hooks_remove_list(self->event, event);
9d239bd9 414 if(event_by_id != NULL) {
415 for(i = 0; i < event_by_id->array->len; i++) {
416 index = g_array_index(event_by_id->array, guint, i);
417 hook = lttv_hooks_by_id_get(self->event_by_id, index);
41a9e0c3 418 if(hook != NULL)
9d239bd9 419 lttv_hooks_remove_list(hook, lttv_hooks_by_id_get(event_by_id, index));
8697a616 420 }
9d239bd9 421 }
8697a616 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) {
77199e93 618 g_assert(key == value);
dc877563 619 *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
620 return TRUE;
621}
622
698e81c2 623static gboolean test_tree(gpointer key, gpointer value, gpointer user_data) {
624
77199e93 625 LttvTracefileContext *tfc = (LttvTracefileContext *)key;
626
627 g_debug("Tracefile name %s, time %lu.%lu, tfi %u, ti %u",
628 g_quark_to_string(ltt_tracefile_name(tfc->tf)),
629 tfc->timestamp.tv_sec, tfc->timestamp.tv_nsec,
630 tfc->index, tfc->t_context->index);
631
632 if(((LttvTracefileContext *)user_data) == (LttvTracefileContext *)value) {
633 g_assert(compare_tracefile(user_data, value) == 0);
634 } else
635 g_assert(compare_tracefile(user_data, value) != 0);
636
637 //g_assert(((LttvTracefileContext *)user_data) != (LttvTracefileContext *)value);
698e81c2 638 return FALSE;
639}
640
641
dc877563 642
8697a616 643void lttv_process_traceset_begin(LttvTracesetContext *self,
644 LttvHooks *before_traceset,
645 LttvHooks *before_trace,
646 LttvHooks *before_tracefile,
647 LttvHooks *event,
648 LttvHooksById *event_by_id)
649{
dc877563 650
8697a616 651 /* simply add hooks in context. _before hooks are called by add_hooks. */
652 /* It calls all before_traceset, before_trace, and before_tracefile hooks. */
653 lttv_traceset_context_add_hooks(self,
654 before_traceset,
655 before_trace,
656 before_tracefile,
657 event,
658 event_by_id);
659
2a2fa4f0 660}
661
36d36c9f 662enum read_state { LAST_NONE, LAST_OK, LAST_EMPTY };
663
8697a616 664/* Note : a _middle must be preceded from a _seek or another middle */
665guint lttv_process_traceset_middle(LttvTracesetContext *self,
666 LttTime end,
b8eccacd 667 guint nb_events,
8697a616 668 const LttvTracesetContextPosition *end_position)
2a2fa4f0 669{
670 GTree *pqueue = self->pqueue;
671
698e81c2 672 guint fac_id, ev_id, id;
2a2fa4f0 673
2a2fa4f0 674 LttvTracefileContext *tfc;
675
eed2ef37 676 LttEvent *e;
677
2a2fa4f0 678 unsigned count = 0;
679
36d36c9f 680 guint read_ret;
681
682 enum read_state last_read_state = LAST_NONE;
698e81c2 683
a54f091a 684 gboolean last_ret = FALSE; /* return value of the last hook list called */
685
dc877563 686 /* Get the next event from the pqueue, call its hooks,
687 reinsert in the pqueue the following event from the same tracefile
688 unless the tracefile is finished or the event is later than the
8697a616 689 end time. */
dc877563 690
ffd54a90 691 while(TRUE) {
dc877563 692 tfc = NULL;
693 g_tree_foreach(pqueue, get_first, &tfc);
33f7a12c 694 /* End of traceset : tfc is NULL */
1d1df11d 695 if(unlikely(tfc == NULL))
a43d67ba 696 {
a43d67ba 697 return count;
698 }
dc877563 699
8697a616 700 /* Have we reached :
701 * - the maximum number of events specified?
702 * - the end position ?
703 * - the end time ?
704 * then the read is finished. We leave the queue in the same state and
705 * break the loop.
706 */
707
1d1df11d 708 if(unlikely(last_ret == TRUE ||
d052ffc3 709 ((count >= nb_events) && (nb_events != G_MAXULONG)) ||
8b0bbe19 710 (end_position!=NULL&&lttv_traceset_context_ctx_pos_compare(self,
711 end_position) == 0)||
1d1df11d 712 ltt_time_compare(end, tfc->timestamp) <= 0))
a43d67ba 713 {
a43d67ba 714 return count;
715 }
36d36c9f 716
308711e5 717 /* Get the tracefile with an event for the smallest time found. If two
718 or more tracefiles have events for the same time, hope that lookup
719 and remove are consistent. */
1986f254 720
721#ifdef DEBUG
77199e93 722 g_debug("test tree before remove");
723 g_tree_foreach(pqueue, test_tree, tfc);
1986f254 724#endif //DEBUG
f95bc830 725 g_tree_remove(pqueue, tfc);
698e81c2 726
1986f254 727#ifdef DEBUG
77199e93 728 g_debug("test tree after remove");
698e81c2 729 g_tree_foreach(pqueue, test_tree, tfc);
1986f254 730#endif //DEBUG
77199e93 731
eed2ef37 732 e = ltt_tracefile_get_event(tfc->tf);
dc877563 733
36d36c9f 734 if(last_read_state != LAST_EMPTY) {
735 /* Only call hooks if the last read has given an event or if we are at the
736 * first pass (not if last read returned end of tracefile) */
737 count++;
738
739 fac_id = ltt_event_facility_id(e);
740 ev_id = ltt_event_eventtype_id(e);
741 id = GET_HOOK_ID(fac_id, ev_id);
742 last_ret = lttv_hooks_call_merge(tfc->event, tfc,
743 lttv_hooks_by_id_get(tfc->event_by_id, id), tfc);
744 }
745
698e81c2 746 read_ret = ltt_tracefile_read(tfc->tf);
747
748 if(likely(!read_ret)) {
77199e93 749 g_debug("An event is ready");
eed2ef37 750 tfc->timestamp = ltt_event_time(e);
77199e93 751
33f7a12c 752 g_tree_insert(pqueue, tfc, tfc);
36d36c9f 753 last_read_state = LAST_OK;
698e81c2 754 } else {
1986f254 755 tfc->timestamp = ltt_time_infinite;
756
36d36c9f 757 if(read_ret == ERANGE) {
758 last_read_state = LAST_EMPTY;
698e81c2 759 g_debug("End of trace");
36d36c9f 760 } else
698e81c2 761 g_error("Error happened in lttv_process_traceset_middle");
dc877563 762 }
763 }
2a2fa4f0 764}
765
766
8697a616 767void lttv_process_traceset_end(LttvTracesetContext *self,
768 LttvHooks *after_traceset,
769 LttvHooks *after_trace,
770 LttvHooks *after_tracefile,
771 LttvHooks *event,
772 LttvHooksById *event_by_id)
2a2fa4f0 773{
8697a616 774 /* Remove hooks from context. _after hooks are called by remove_hooks. */
775 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
776 lttv_traceset_context_remove_hooks(self,
777 after_traceset,
778 after_trace,
779 after_tracefile,
780 event,
781 event_by_id);
782}
2a2fa4f0 783
27304273 784/* Subtile modification :
785 * if tracefile has no event at or after the time requested, it is not put in
786 * the queue, as the next read would fail. */
8697a616 787void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
788{
789 guint i, nb_tracefile;
2a2fa4f0 790
eed2ef37 791 gint ret;
792
1986f254 793 LttvTracefileContext **tfc;
2a2fa4f0 794
a5ba1787 795 GTree *pqueue = self->ts_context->pqueue;
796
eed2ef37 797 nb_tracefile = self->tracefiles->len;
dc877563 798
8697a616 799 for(i = 0 ; i < nb_tracefile ; i++) {
1986f254 800 tfc = &g_array_index(self->tracefiles, LttvTracefileContext*, i);
77199e93 801
1986f254 802 g_tree_remove(pqueue, *tfc);
77199e93 803
1986f254 804 ret = ltt_tracefile_seek_time((*tfc)->tf, start);
27304273 805 if(ret == EPERM) g_error("error in lttv_process_trace_seek_time seek");
27304273 806
807 if(ret == 0) { /* not ERANGE especially */
1986f254 808 (*tfc)->timestamp = ltt_event_time(ltt_tracefile_get_event((*tfc)->tf));
809 g_tree_insert(pqueue, (*tfc), (*tfc));
810 } else {
811 (*tfc)->timestamp = ltt_time_infinite;
27304273 812 }
8697a616 813 }
814}
dc877563 815
2a2fa4f0 816
8697a616 817void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
818{
819 guint i, nb_trace;
2a2fa4f0 820
8697a616 821 LttvTraceContext *tc;
2a2fa4f0 822
8697a616 823 nb_trace = lttv_traceset_number(self->ts);
824 for(i = 0 ; i < nb_trace ; i++) {
825 tc = self->traces[i];
826 lttv_process_trace_seek_time(tc, start);
827 }
dc877563 828}
b445142a 829
308711e5 830
8697a616 831gboolean lttv_process_traceset_seek_position(LttvTracesetContext *self,
832 const LttvTracesetContextPosition *pos)
308711e5 833{
27304273 834 guint i;
308711e5 835
27304273 836 g_tree_destroy(self->pqueue);
837 self->pqueue = g_tree_new(compare_tracefile);
8697a616 838
27304273 839 for(i=0;i<pos->ep->len; i++) {
1986f254 840 LttEventPosition **ep = &g_array_index(pos->ep, LttEventPosition*, i);
841 LttvTracefileContext **tfc =
842 &g_array_index(pos->tfc, LttvTracefileContext*, i);
843 if(*ep != NULL) {
2c82c4dc 844 if(ltt_tracefile_seek_position((*tfc)->tf, *ep) != 0)
845 return 1;
1986f254 846 (*tfc)->timestamp = ltt_event_time(ltt_tracefile_get_event((*tfc)->tf));
847 g_tree_insert(self->pqueue, (*tfc), (*tfc));
848 } else {
849 (*tfc)->timestamp = ltt_time_infinite;
850 }
308711e5 851 }
2c82c4dc 852 return 0;
308711e5 853}
854
855
8697a616 856
b445142a 857static LttField *
eed2ef37 858find_field(LttEventType *et, const GQuark field)
b445142a 859{
860 LttType *t;
861
862 LttField *f;
863
864 guint i, nb;
865
eed2ef37 866 GQuark name;
b445142a 867
eed2ef37 868 /* Field is unset */
869 if(field == 0) return NULL;
870
b445142a 871 f = ltt_eventtype_field(et);
872 t = ltt_eventtype_type(et);
873 g_assert(ltt_type_class(t) == LTT_STRUCT);
874 nb = ltt_type_member_number(t);
875 for(i = 0 ; i < nb ; i++) {
876 ltt_type_member_type(t, i, &name);
eed2ef37 877 if(name == field) break;
b445142a 878 }
879 g_assert(i < nb);
880 return ltt_field_member(f, i);
881}
882
eed2ef37 883LttvTraceHookByFacility *lttv_trace_hook_get_fac(LttvTraceHook *th,
884 guint facility_id)
885{
886 return &g_array_index(th->fac_index, LttvTraceHookByFacility, facility_id);
887}
888
889/* Get the first facility corresponding to the name. As the types must be
890 * compatible, it is relevant to use the field name and sizes of the first
891 * facility to create data structures and assume the data will be compatible
892 * thorough the trace */
893LttvTraceHookByFacility *lttv_trace_hook_get_first(LttvTraceHook *th)
894{
895 g_assert(th->fac_list->len > 0);
896 return g_array_index(th->fac_list, LttvTraceHookByFacility*, 0);
897}
898
b445142a 899
eed2ef37 900/* Returns 0 on success, -1 if fails. */
901gint
902lttv_trace_find_hook(LttTrace *t, GQuark facility, GQuark event,
2c82c4dc 903 GQuark field1, GQuark field2, GQuark field3, LttvHook h, gpointer hook_data,
904 LttvTraceHook *th)
b445142a 905{
906 LttFacility *f;
907
eed2ef37 908 LttEventType *et, *first_et;
909
910 GArray *facilities;
911
d052ffc3 912 guint i, fac_id, ev_id;
b445142a 913
eed2ef37 914 LttvTraceHookByFacility *thf, *first_thf;
b445142a 915
eed2ef37 916 facilities = ltt_trace_facility_get_by_name(t, facility);
021eeb41 917
eed2ef37 918 if(unlikely(facilities == NULL)) goto facility_error;
919
920 th->fac_index = g_array_sized_new(FALSE, TRUE,
921 sizeof(LttvTraceHookByFacility),
922 NUM_FACILITIES);
923 th->fac_index = g_array_set_size(th->fac_index, NUM_FACILITIES);
b445142a 924
eed2ef37 925 th->fac_list = g_array_sized_new(FALSE, TRUE,
926 sizeof(LttvTraceHookByFacility*),
927 facilities->len);
928 th->fac_list = g_array_set_size(th->fac_list, facilities->len);
929
930 fac_id = g_array_index(facilities, guint, 0);
931 f = ltt_trace_get_facility_by_num(t, fac_id);
932
cb03932a 933 et = ltt_facility_eventtype_get_by_name(f, event);
eed2ef37 934 if(unlikely(et == NULL)) goto event_error;
935
936 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
1986f254 937 g_array_index(th->fac_list, LttvTraceHookByFacility*, 0) = thf;
9d239bd9 938
d052ffc3 939 ev_id = ltt_eventtype_id(et);
940
eed2ef37 941 thf->h = h;
d052ffc3 942 thf->id = GET_HOOK_ID(fac_id, ev_id);
eed2ef37 943 thf->f1 = find_field(et, field1);
944 thf->f2 = find_field(et, field2);
945 thf->f3 = find_field(et, field3);
2c82c4dc 946 thf->hook_data = hook_data;
eed2ef37 947
948 first_thf = thf;
826f1ab2 949 first_et = et;
eed2ef37 950
951 /* Check for type compatibility too */
952 for(i=1;i<facilities->len;i++) {
953 fac_id = g_array_index(facilities, guint, i);
954 f = ltt_trace_get_facility_by_num(t, fac_id);
955
956 et = ltt_facility_eventtype_get_by_name(f, ltt_eventtype_name(et));
957 if(unlikely(et == NULL)) goto event_error;
958
959 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
1986f254 960 g_array_index(th->fac_list, LttvTraceHookByFacility*, i) = thf;
d052ffc3 961 ev_id = ltt_eventtype_id(et);
eed2ef37 962 thf->h = h;
d052ffc3 963 thf->id = GET_HOOK_ID(fac_id, ev_id);
eed2ef37 964 thf->f1 = find_field(et, field1);
965 if(check_fields_compatibility(first_et, et,
966 first_thf->f1, thf->f1))
967 goto type_error;
968
969 thf->f2 = find_field(et, field2);
970 if(check_fields_compatibility(first_et, et,
971 first_thf->f2, thf->f2))
972 goto type_error;
973
974 thf->f3 = find_field(et, field3);
975 if(check_fields_compatibility(first_et, et,
976 first_thf->f3, thf->f3))
977 goto type_error;
2c82c4dc 978 thf->hook_data = hook_data;
eed2ef37 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{
27304273 1009 LttvTracesetContextPosition *pos = g_new(LttvTracesetContextPosition,1);
1010 pos->ep = g_array_sized_new(FALSE, TRUE, sizeof(LttEventPosition*),
1011 10);
1012 pos->tfc = g_array_sized_new(FALSE, TRUE, sizeof(LttvTracefileContext*),
1013 10);
1014 pos->timestamp = ltt_time_infinite;
1015 return pos;
5e2c04a2 1016}
1017
1986f254 1018/* Save all positions, the ones not in the pqueue will have NULL
1019 * ep. */
27304273 1020void lttv_traceset_context_position_save(const LttvTracesetContext *self,
1021 LttvTracesetContextPosition *pos)
1022{
1986f254 1023 guint i;
1024 guint num_traces = lttv_traceset_number(self->ts);
1025
1026 for(i=0; i<num_traces;i++) {
1027 GArray * tracefiles = self->traces[i]->tracefiles;
1028 guint j;
1029 guint num_tracefiles = tracefiles->len;
1030
1031 for(j=0;j<num_tracefiles;j++) {
1032 LttvTracefileContext **tfc = &g_array_index(tracefiles,
1033 LttvTracefileContext*, j);
1034
1035 LttEvent *event = ltt_tracefile_get_event((*tfc)->tf);
1036 LttEventPosition *ep;
1037
1038 if(ltt_time_compare((*tfc)->timestamp, ltt_time_infinite) != 0) {
1039 ep = ltt_event_position_new();
1040 ltt_event_position(event, ep);
1041 if(ltt_time_compare((*tfc)->timestamp, pos->timestamp) < 0)
1042 pos->timestamp = (*tfc)->timestamp;
1043 } else {
1044 ep = NULL;
1045 }
1046 g_array_append_val(pos->tfc, *tfc);
1047 g_array_append_val(pos->ep, ep);
1048 }
1049
1050 }
8697a616 1051}
1052
1053void lttv_traceset_context_position_destroy(LttvTracesetContextPosition *pos)
1054{
27304273 1055 int i;
1986f254 1056 LttEventPosition **ep;
1057
1058 for(i=0;i<pos->ep->len;i++) {
1059 ep = &g_array_index(pos->ep, LttEventPosition*, i);
1060 if(*ep != NULL)
1061 g_free(*ep);
1062 }
27304273 1063 g_array_free(pos->ep, TRUE);
1064 g_array_free(pos->tfc, TRUE);
1065 g_free(pos);
8697a616 1066}
1067
5e2c04a2 1068void lttv_traceset_context_position_copy(LttvTracesetContextPosition *dest,
1069 const LttvTracesetContextPosition *src)
1070{
27304273 1071 int i;
1986f254 1072 LttEventPosition **src_ep, **dest_ep;
5e2c04a2 1073
27304273 1074 g_array_set_size(dest->ep, src->ep->len);
1075 g_array_set_size(dest->tfc, src->tfc->len);
1076
1077 for(i=0;i<src->ep->len;i++) {
1986f254 1078 src_ep = &g_array_index(src->ep, LttEventPosition*, i);
1079 dest_ep = &g_array_index(dest->ep, LttEventPosition*, i);
1080 if(*src_ep != NULL) {
1081 *dest_ep = ltt_event_position_new();
1082 ltt_event_position_copy(
1083 *dest_ep,
1084 *src_ep);
1085 } else
1086 *dest_ep = NULL;
27304273 1087 }
1088 for(i=0;i<src->tfc->len;i++) {
1089 g_array_index(dest->tfc, LttvTracefileContext*, i) =
1090 g_array_index(src->tfc, LttvTracefileContext*, i);
5e2c04a2 1091 }
5e2c04a2 1092 dest->timestamp = src->timestamp;
1093}
1094
8697a616 1095gint lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext *self,
1096 const LttvTracesetContextPosition *pos)
1097{
27304273 1098 int i;
826f1ab2 1099 int ret = 0;
2c82c4dc 1100
1101 if(pos->ep->len == 0) {
1102 if(lttv_traceset_number(self->ts) == 0) return 0;
1103 else return 1;
1104 }
1105 if(lttv_traceset_number(self->ts) == 0)
1106 return -1;
1107
27304273 1108 for(i=0;i<pos->ep->len;i++) {
1109 LttEventPosition *ep = g_array_index(pos->ep, LttEventPosition*, i);
1110 LttvTracefileContext *tfc =
1111 g_array_index(pos->tfc, LttvTracefileContext*, i);
1986f254 1112
1113 if(ep == NULL) {
1114 if(ltt_time_compare(tfc->timestamp, ltt_time_infinite) != 0) {
1115 ret = -1;
1116 }
1117 } else {
1118 if(ltt_time_compare(tfc->timestamp, ltt_time_infinite) == 0) {
1119 ret = 1;
1120 } else {
1121 LttEvent *event = ltt_tracefile_get_event(tfc->tf);
8697a616 1122
1986f254 1123 ret = ltt_event_position_compare((LttEventPosition*)event,
1124 ep);
1125 }
1126 }
27304273 1127 if(ret != 0) return ret;
8697a616 1128
8697a616 1129 }
1130 return 0;
1131}
1132
1133
1134gint lttv_traceset_context_pos_pos_compare(
1135 const LttvTracesetContextPosition *pos1,
1136 const LttvTracesetContextPosition *pos2)
1137{
27304273 1138 int i, j;
1139 int ret;
8697a616 1140
2c82c4dc 1141 if(pos1->ep->len == 0) {
1142 if(pos2->ep->len == 0) return 0;
1143 else return 1;
1144 }
1145 if(pos2->ep->len == 0)
1146 return -1;
1147
27304273 1148 for(i=0;i<pos1->ep->len;i++) {
1149 LttEventPosition *ep1 = g_array_index(pos1->ep, LttEventPosition*, i);
1986f254 1150 LttvTracefileContext *tfc1 = g_array_index(pos1->tfc,
1151 LttvTracefileContext*, i);
27304273 1152
1986f254 1153 if(ep1 != NULL) {
1154 for(j=0;j<pos2->ep->len;j++) {
1155 LttEventPosition *ep2 = g_array_index(pos2->ep, LttEventPosition*, j);
1156 LttvTracefileContext *tfc2 = g_array_index(pos2->tfc,
1157 LttvTracefileContext*, j);
1158 if(tfc1 == tfc2) {
1159 if(ep2 != NULL)
1160 ret = ltt_event_position_compare(ep1, ep2);
1161 else
1162 ret = -1;
1163
1164 if(ret != 0) return ret;
1165 }
1166 }
1167 } else {
1168 for(j=0;j<pos2->ep->len;j++) {
1169 LttEventPosition *ep2 = g_array_index(pos2->ep, LttEventPosition*, j);
1170 LttvTracefileContext *tfc2 = g_array_index(pos2->tfc,
1171 LttvTracefileContext*, j);
1172 if(tfc1 == tfc2) {
1173 if(ep2 != NULL) ret = 1;
1174 }
27304273 1175 }
8697a616 1176 }
1177 }
1178 return 0;
1179}
1180
1181
2d262115 1182LttTime lttv_traceset_context_position_get_time(
1183 const LttvTracesetContextPosition *pos)
1184{
1185 return pos->timestamp;
1186}
1187
1188
1189LttvTracefileContext *lttv_traceset_context_get_current_tfc(LttvTracesetContext *self)
1190{
1191 GTree *pqueue = self->pqueue;
b56b5fec 1192 LttvTracefileContext *tfc = NULL;
2d262115 1193
1194 g_tree_foreach(pqueue, get_first, &tfc);
1195
1196 return tfc;
1197}
79257ba5 1198#if 0
2c82c4dc 1199/* lttv_process_traceset_synchronize_tracefiles
1200 *
1201 * Use the sync_position field of the trace set context to synchronize each
1202 * tracefile with the previously saved position.
1203 *
1204 * If no previous position has been saved, it simply does nothing.
1205 */
1206void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext *tsc)
1207{
1208 g_assert(lttv_process_traceset_seek_position(tsc, tsc->sync_position) == 0);
1209}
1210
1211
1212
1213
1214void lttv_process_traceset_get_sync_data(LttvTracesetContext *tsc)
1215{
1216 lttv_traceset_context_position_save(tsc, tsc->sync_position);
1217}
1218
79257ba5 1219#endif //0
2c82c4dc 1220
This page took 0.091583 seconds and 4 git commands to generate.