fix back textcontree tree compare function : was allright before
[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
8697a616 662/* Note : a _middle must be preceded from a _seek or another middle */
663guint lttv_process_traceset_middle(LttvTracesetContext *self,
664 LttTime end,
b8eccacd 665 guint nb_events,
8697a616 666 const LttvTracesetContextPosition *end_position)
2a2fa4f0 667{
668 GTree *pqueue = self->pqueue;
669
698e81c2 670 guint fac_id, ev_id, id;
2a2fa4f0 671
2a2fa4f0 672 LttvTracefileContext *tfc;
673
eed2ef37 674 LttEvent *e;
675
2a2fa4f0 676 unsigned count = 0;
677
698e81c2 678 guint read_ret = FALSE;
679
a54f091a 680 gboolean last_ret = FALSE; /* return value of the last hook list called */
681
dc877563 682 /* Get the next event from the pqueue, call its hooks,
683 reinsert in the pqueue the following event from the same tracefile
684 unless the tracefile is finished or the event is later than the
8697a616 685 end time. */
dc877563 686
ffd54a90 687 while(TRUE) {
dc877563 688 tfc = NULL;
689 g_tree_foreach(pqueue, get_first, &tfc);
33f7a12c 690 /* End of traceset : tfc is NULL */
1d1df11d 691 if(unlikely(tfc == NULL))
a43d67ba 692 {
a43d67ba 693 return count;
694 }
dc877563 695
8697a616 696 /* Have we reached :
697 * - the maximum number of events specified?
698 * - the end position ?
699 * - the end time ?
700 * then the read is finished. We leave the queue in the same state and
701 * break the loop.
702 */
703
1d1df11d 704 if(unlikely(last_ret == TRUE ||
d052ffc3 705 ((count >= nb_events) && (nb_events != G_MAXULONG)) ||
8b0bbe19 706 (end_position!=NULL&&lttv_traceset_context_ctx_pos_compare(self,
707 end_position) == 0)||
1d1df11d 708 ltt_time_compare(end, tfc->timestamp) <= 0))
a43d67ba 709 {
a43d67ba 710 return count;
711 }
2a2fa4f0 712
308711e5 713 /* Get the tracefile with an event for the smallest time found. If two
714 or more tracefiles have events for the same time, hope that lookup
715 and remove are consistent. */
1986f254 716
717#ifdef DEBUG
77199e93 718 g_debug("test tree before remove");
719 g_tree_foreach(pqueue, test_tree, tfc);
1986f254 720#endif //DEBUG
f95bc830 721 g_tree_remove(pqueue, tfc);
698e81c2 722
1986f254 723#ifdef DEBUG
77199e93 724 g_debug("test tree after remove");
698e81c2 725 g_tree_foreach(pqueue, test_tree, tfc);
1986f254 726#endif //DEBUG
77199e93 727
2a2fa4f0 728 count++;
eed2ef37 729
730 e = ltt_tracefile_get_event(tfc->tf);
698e81c2 731 fac_id = ltt_event_facility_id(e);
732 ev_id = ltt_event_eventtype_id(e);
733 id = GET_HOOK_ID(fac_id, ev_id);
a54f091a 734 last_ret = lttv_hooks_call_merge(tfc->event, tfc,
8697a616 735 lttv_hooks_by_id_get(tfc->event_by_id, id), tfc);
dc877563 736
698e81c2 737 read_ret = ltt_tracefile_read(tfc->tf);
738
739 if(likely(!read_ret)) {
77199e93 740 g_debug("An event is ready");
eed2ef37 741 tfc->timestamp = ltt_event_time(e);
77199e93 742
33f7a12c 743 g_tree_insert(pqueue, tfc, tfc);
698e81c2 744 } else {
1986f254 745 tfc->timestamp = ltt_time_infinite;
746
698e81c2 747 if(read_ret == ERANGE)
748 g_debug("End of trace");
749 else
750 g_error("Error happened in lttv_process_traceset_middle");
dc877563 751 }
752 }
2a2fa4f0 753}
754
755
8697a616 756void lttv_process_traceset_end(LttvTracesetContext *self,
757 LttvHooks *after_traceset,
758 LttvHooks *after_trace,
759 LttvHooks *after_tracefile,
760 LttvHooks *event,
761 LttvHooksById *event_by_id)
2a2fa4f0 762{
8697a616 763 /* Remove hooks from context. _after hooks are called by remove_hooks. */
764 /* It calls all after_traceset, after_trace, and after_tracefile hooks. */
765 lttv_traceset_context_remove_hooks(self,
766 after_traceset,
767 after_trace,
768 after_tracefile,
769 event,
770 event_by_id);
771}
2a2fa4f0 772
27304273 773/* Subtile modification :
774 * if tracefile has no event at or after the time requested, it is not put in
775 * the queue, as the next read would fail. */
8697a616 776void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
777{
778 guint i, nb_tracefile;
2a2fa4f0 779
eed2ef37 780 gint ret;
781
1986f254 782 LttvTracefileContext **tfc;
2a2fa4f0 783
a5ba1787 784 GTree *pqueue = self->ts_context->pqueue;
785
eed2ef37 786 nb_tracefile = self->tracefiles->len;
dc877563 787
8697a616 788 for(i = 0 ; i < nb_tracefile ; i++) {
1986f254 789 tfc = &g_array_index(self->tracefiles, LttvTracefileContext*, i);
77199e93 790
1986f254 791 g_tree_remove(pqueue, *tfc);
77199e93 792
1986f254 793 ret = ltt_tracefile_seek_time((*tfc)->tf, start);
27304273 794 if(ret == EPERM) g_error("error in lttv_process_trace_seek_time seek");
27304273 795
796 if(ret == 0) { /* not ERANGE especially */
1986f254 797 (*tfc)->timestamp = ltt_event_time(ltt_tracefile_get_event((*tfc)->tf));
798 g_tree_insert(pqueue, (*tfc), (*tfc));
799 } else {
800 (*tfc)->timestamp = ltt_time_infinite;
27304273 801 }
8697a616 802 }
803}
dc877563 804
2a2fa4f0 805
8697a616 806void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
807{
808 guint i, nb_trace;
2a2fa4f0 809
8697a616 810 LttvTraceContext *tc;
2a2fa4f0 811
8697a616 812 nb_trace = lttv_traceset_number(self->ts);
813 for(i = 0 ; i < nb_trace ; i++) {
814 tc = self->traces[i];
815 lttv_process_trace_seek_time(tc, start);
816 }
dc877563 817}
b445142a 818
308711e5 819
8697a616 820gboolean lttv_process_traceset_seek_position(LttvTracesetContext *self,
821 const LttvTracesetContextPosition *pos)
308711e5 822{
27304273 823 guint i;
308711e5 824
27304273 825 g_tree_destroy(self->pqueue);
826 self->pqueue = g_tree_new(compare_tracefile);
8697a616 827
27304273 828 for(i=0;i<pos->ep->len; i++) {
1986f254 829 LttEventPosition **ep = &g_array_index(pos->ep, LttEventPosition*, i);
830 LttvTracefileContext **tfc =
831 &g_array_index(pos->tfc, LttvTracefileContext*, i);
832 if(*ep != NULL) {
2c82c4dc 833 if(ltt_tracefile_seek_position((*tfc)->tf, *ep) != 0)
834 return 1;
1986f254 835 (*tfc)->timestamp = ltt_event_time(ltt_tracefile_get_event((*tfc)->tf));
836 g_tree_insert(self->pqueue, (*tfc), (*tfc));
837 } else {
838 (*tfc)->timestamp = ltt_time_infinite;
839 }
308711e5 840 }
2c82c4dc 841 return 0;
308711e5 842}
843
844
8697a616 845
b445142a 846static LttField *
eed2ef37 847find_field(LttEventType *et, const GQuark field)
b445142a 848{
849 LttType *t;
850
851 LttField *f;
852
853 guint i, nb;
854
eed2ef37 855 GQuark name;
b445142a 856
eed2ef37 857 /* Field is unset */
858 if(field == 0) return NULL;
859
b445142a 860 f = ltt_eventtype_field(et);
861 t = ltt_eventtype_type(et);
862 g_assert(ltt_type_class(t) == LTT_STRUCT);
863 nb = ltt_type_member_number(t);
864 for(i = 0 ; i < nb ; i++) {
865 ltt_type_member_type(t, i, &name);
eed2ef37 866 if(name == field) break;
b445142a 867 }
868 g_assert(i < nb);
869 return ltt_field_member(f, i);
870}
871
eed2ef37 872LttvTraceHookByFacility *lttv_trace_hook_get_fac(LttvTraceHook *th,
873 guint facility_id)
874{
875 return &g_array_index(th->fac_index, LttvTraceHookByFacility, facility_id);
876}
877
878/* Get the first facility corresponding to the name. As the types must be
879 * compatible, it is relevant to use the field name and sizes of the first
880 * facility to create data structures and assume the data will be compatible
881 * thorough the trace */
882LttvTraceHookByFacility *lttv_trace_hook_get_first(LttvTraceHook *th)
883{
884 g_assert(th->fac_list->len > 0);
885 return g_array_index(th->fac_list, LttvTraceHookByFacility*, 0);
886}
887
b445142a 888
eed2ef37 889/* Returns 0 on success, -1 if fails. */
890gint
891lttv_trace_find_hook(LttTrace *t, GQuark facility, GQuark event,
2c82c4dc 892 GQuark field1, GQuark field2, GQuark field3, LttvHook h, gpointer hook_data,
893 LttvTraceHook *th)
b445142a 894{
895 LttFacility *f;
896
eed2ef37 897 LttEventType *et, *first_et;
898
899 GArray *facilities;
900
d052ffc3 901 guint i, fac_id, ev_id;
b445142a 902
eed2ef37 903 LttvTraceHookByFacility *thf, *first_thf;
b445142a 904
eed2ef37 905 facilities = ltt_trace_facility_get_by_name(t, facility);
021eeb41 906
eed2ef37 907 if(unlikely(facilities == NULL)) goto facility_error;
908
909 th->fac_index = g_array_sized_new(FALSE, TRUE,
910 sizeof(LttvTraceHookByFacility),
911 NUM_FACILITIES);
912 th->fac_index = g_array_set_size(th->fac_index, NUM_FACILITIES);
b445142a 913
eed2ef37 914 th->fac_list = g_array_sized_new(FALSE, TRUE,
915 sizeof(LttvTraceHookByFacility*),
916 facilities->len);
917 th->fac_list = g_array_set_size(th->fac_list, facilities->len);
918
919 fac_id = g_array_index(facilities, guint, 0);
920 f = ltt_trace_get_facility_by_num(t, fac_id);
921
cb03932a 922 et = ltt_facility_eventtype_get_by_name(f, event);
eed2ef37 923 if(unlikely(et == NULL)) goto event_error;
924
925 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
1986f254 926 g_array_index(th->fac_list, LttvTraceHookByFacility*, 0) = thf;
9d239bd9 927
d052ffc3 928 ev_id = ltt_eventtype_id(et);
929
eed2ef37 930 thf->h = h;
d052ffc3 931 thf->id = GET_HOOK_ID(fac_id, ev_id);
eed2ef37 932 thf->f1 = find_field(et, field1);
933 thf->f2 = find_field(et, field2);
934 thf->f3 = find_field(et, field3);
2c82c4dc 935 thf->hook_data = hook_data;
eed2ef37 936
937 first_thf = thf;
826f1ab2 938 first_et = et;
eed2ef37 939
940 /* Check for type compatibility too */
941 for(i=1;i<facilities->len;i++) {
942 fac_id = g_array_index(facilities, guint, i);
943 f = ltt_trace_get_facility_by_num(t, fac_id);
944
945 et = ltt_facility_eventtype_get_by_name(f, ltt_eventtype_name(et));
946 if(unlikely(et == NULL)) goto event_error;
947
948 thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id);
1986f254 949 g_array_index(th->fac_list, LttvTraceHookByFacility*, i) = thf;
d052ffc3 950 ev_id = ltt_eventtype_id(et);
eed2ef37 951 thf->h = h;
d052ffc3 952 thf->id = GET_HOOK_ID(fac_id, ev_id);
eed2ef37 953 thf->f1 = find_field(et, field1);
954 if(check_fields_compatibility(first_et, et,
955 first_thf->f1, thf->f1))
956 goto type_error;
957
958 thf->f2 = find_field(et, field2);
959 if(check_fields_compatibility(first_et, et,
960 first_thf->f2, thf->f2))
961 goto type_error;
962
963 thf->f3 = find_field(et, field3);
964 if(check_fields_compatibility(first_et, et,
965 first_thf->f3, thf->f3))
966 goto type_error;
2c82c4dc 967 thf->hook_data = hook_data;
eed2ef37 968 }
969
970 return 0;
971
972type_error:
973 goto free;
974event_error:
975 g_error("Event type %s does not exist",
976 g_quark_to_string(ltt_eventtype_name(et)));
977 goto free;
978facility_error:
979 g_error("No %s facility", g_quark_to_string(facility));
980 goto free;
981free:
982 g_array_free(th->fac_index, TRUE);
983 g_array_free(th->fac_list, TRUE);
984 th->fac_index = NULL;
985 th->fac_list = NULL;
986 return -1;
987}
988
989void lttv_trace_hook_destroy(LttvTraceHook *th)
990{
991 g_array_free(th->fac_index, TRUE);
992 g_array_free(th->fac_list, TRUE);
b445142a 993}
994
995
8b0bbe19 996LttvTracesetContextPosition *lttv_traceset_context_position_new()
5e2c04a2 997{
27304273 998 LttvTracesetContextPosition *pos = g_new(LttvTracesetContextPosition,1);
999 pos->ep = g_array_sized_new(FALSE, TRUE, sizeof(LttEventPosition*),
1000 10);
1001 pos->tfc = g_array_sized_new(FALSE, TRUE, sizeof(LttvTracefileContext*),
1002 10);
1003 pos->timestamp = ltt_time_infinite;
1004 return pos;
5e2c04a2 1005}
1006
1986f254 1007/* Save all positions, the ones not in the pqueue will have NULL
1008 * ep. */
27304273 1009void lttv_traceset_context_position_save(const LttvTracesetContext *self,
1010 LttvTracesetContextPosition *pos)
1011{
1986f254 1012 guint i;
1013 guint num_traces = lttv_traceset_number(self->ts);
1014
1015 for(i=0; i<num_traces;i++) {
1016 GArray * tracefiles = self->traces[i]->tracefiles;
1017 guint j;
1018 guint num_tracefiles = tracefiles->len;
1019
1020 for(j=0;j<num_tracefiles;j++) {
1021 LttvTracefileContext **tfc = &g_array_index(tracefiles,
1022 LttvTracefileContext*, j);
1023
1024 LttEvent *event = ltt_tracefile_get_event((*tfc)->tf);
1025 LttEventPosition *ep;
1026
1027 if(ltt_time_compare((*tfc)->timestamp, ltt_time_infinite) != 0) {
1028 ep = ltt_event_position_new();
1029 ltt_event_position(event, ep);
1030 if(ltt_time_compare((*tfc)->timestamp, pos->timestamp) < 0)
1031 pos->timestamp = (*tfc)->timestamp;
1032 } else {
1033 ep = NULL;
1034 }
1035 g_array_append_val(pos->tfc, *tfc);
1036 g_array_append_val(pos->ep, ep);
1037 }
1038
1039 }
8697a616 1040}
1041
1042void lttv_traceset_context_position_destroy(LttvTracesetContextPosition *pos)
1043{
27304273 1044 int i;
1986f254 1045 LttEventPosition **ep;
1046
1047 for(i=0;i<pos->ep->len;i++) {
1048 ep = &g_array_index(pos->ep, LttEventPosition*, i);
1049 if(*ep != NULL)
1050 g_free(*ep);
1051 }
27304273 1052 g_array_free(pos->ep, TRUE);
1053 g_array_free(pos->tfc, TRUE);
1054 g_free(pos);
8697a616 1055}
1056
5e2c04a2 1057void lttv_traceset_context_position_copy(LttvTracesetContextPosition *dest,
1058 const LttvTracesetContextPosition *src)
1059{
27304273 1060 int i;
1986f254 1061 LttEventPosition **src_ep, **dest_ep;
5e2c04a2 1062
27304273 1063 g_array_set_size(dest->ep, src->ep->len);
1064 g_array_set_size(dest->tfc, src->tfc->len);
1065
1066 for(i=0;i<src->ep->len;i++) {
1986f254 1067 src_ep = &g_array_index(src->ep, LttEventPosition*, i);
1068 dest_ep = &g_array_index(dest->ep, LttEventPosition*, i);
1069 if(*src_ep != NULL) {
1070 *dest_ep = ltt_event_position_new();
1071 ltt_event_position_copy(
1072 *dest_ep,
1073 *src_ep);
1074 } else
1075 *dest_ep = NULL;
27304273 1076 }
1077 for(i=0;i<src->tfc->len;i++) {
1078 g_array_index(dest->tfc, LttvTracefileContext*, i) =
1079 g_array_index(src->tfc, LttvTracefileContext*, i);
5e2c04a2 1080 }
5e2c04a2 1081 dest->timestamp = src->timestamp;
1082}
1083
8697a616 1084gint lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext *self,
1085 const LttvTracesetContextPosition *pos)
1086{
27304273 1087 int i;
826f1ab2 1088 int ret = 0;
2c82c4dc 1089
1090 if(pos->ep->len == 0) {
1091 if(lttv_traceset_number(self->ts) == 0) return 0;
1092 else return 1;
1093 }
1094 if(lttv_traceset_number(self->ts) == 0)
1095 return -1;
1096
27304273 1097 for(i=0;i<pos->ep->len;i++) {
1098 LttEventPosition *ep = g_array_index(pos->ep, LttEventPosition*, i);
1099 LttvTracefileContext *tfc =
1100 g_array_index(pos->tfc, LttvTracefileContext*, i);
1986f254 1101
1102 if(ep == NULL) {
1103 if(ltt_time_compare(tfc->timestamp, ltt_time_infinite) != 0) {
1104 ret = -1;
1105 }
1106 } else {
1107 if(ltt_time_compare(tfc->timestamp, ltt_time_infinite) == 0) {
1108 ret = 1;
1109 } else {
1110 LttEvent *event = ltt_tracefile_get_event(tfc->tf);
8697a616 1111
1986f254 1112 ret = ltt_event_position_compare((LttEventPosition*)event,
1113 ep);
1114 }
1115 }
27304273 1116 if(ret != 0) return ret;
8697a616 1117
8697a616 1118 }
1119 return 0;
1120}
1121
1122
1123gint lttv_traceset_context_pos_pos_compare(
1124 const LttvTracesetContextPosition *pos1,
1125 const LttvTracesetContextPosition *pos2)
1126{
27304273 1127 int i, j;
1128 int ret;
8697a616 1129
2c82c4dc 1130 if(pos1->ep->len == 0) {
1131 if(pos2->ep->len == 0) return 0;
1132 else return 1;
1133 }
1134 if(pos2->ep->len == 0)
1135 return -1;
1136
27304273 1137 for(i=0;i<pos1->ep->len;i++) {
1138 LttEventPosition *ep1 = g_array_index(pos1->ep, LttEventPosition*, i);
1986f254 1139 LttvTracefileContext *tfc1 = g_array_index(pos1->tfc,
1140 LttvTracefileContext*, i);
27304273 1141
1986f254 1142 if(ep1 != NULL) {
1143 for(j=0;j<pos2->ep->len;j++) {
1144 LttEventPosition *ep2 = g_array_index(pos2->ep, LttEventPosition*, j);
1145 LttvTracefileContext *tfc2 = g_array_index(pos2->tfc,
1146 LttvTracefileContext*, j);
1147 if(tfc1 == tfc2) {
1148 if(ep2 != NULL)
1149 ret = ltt_event_position_compare(ep1, ep2);
1150 else
1151 ret = -1;
1152
1153 if(ret != 0) return ret;
1154 }
1155 }
1156 } else {
1157 for(j=0;j<pos2->ep->len;j++) {
1158 LttEventPosition *ep2 = g_array_index(pos2->ep, LttEventPosition*, j);
1159 LttvTracefileContext *tfc2 = g_array_index(pos2->tfc,
1160 LttvTracefileContext*, j);
1161 if(tfc1 == tfc2) {
1162 if(ep2 != NULL) ret = 1;
1163 }
27304273 1164 }
8697a616 1165 }
1166 }
1167 return 0;
1168}
1169
1170
2d262115 1171LttTime lttv_traceset_context_position_get_time(
1172 const LttvTracesetContextPosition *pos)
1173{
1174 return pos->timestamp;
1175}
1176
1177
1178LttvTracefileContext *lttv_traceset_context_get_current_tfc(LttvTracesetContext *self)
1179{
1180 GTree *pqueue = self->pqueue;
b56b5fec 1181 LttvTracefileContext *tfc = NULL;
2d262115 1182
1183 g_tree_foreach(pqueue, get_first, &tfc);
1184
1185 return tfc;
1186}
79257ba5 1187#if 0
2c82c4dc 1188/* lttv_process_traceset_synchronize_tracefiles
1189 *
1190 * Use the sync_position field of the trace set context to synchronize each
1191 * tracefile with the previously saved position.
1192 *
1193 * If no previous position has been saved, it simply does nothing.
1194 */
1195void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext *tsc)
1196{
1197 g_assert(lttv_process_traceset_seek_position(tsc, tsc->sync_position) == 0);
1198}
1199
1200
1201
1202
1203void lttv_process_traceset_get_sync_data(LttvTracesetContext *tsc)
1204{
1205 lttv_traceset_context_position_save(tsc, tsc->sync_position);
1206}
1207
79257ba5 1208#endif //0
2c82c4dc 1209
This page took 0.093117 seconds and 4 git commands to generate.