Add config.h support : will fix the LARGEFILE problem
[lttv.git] / ltt / branches / poly / ltt / event.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Xiangxiu Yang
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
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26
27 #include <asm/types.h>
28 #include <linux/byteorder/swab.h>
29
30 #include "parser.h"
31 #include <ltt/ltt.h>
32 #include "ltt-private.h"
33 #include <ltt/event.h>
34 #include <ltt/trace.h>
35 #include <ltt/ltt-types.h>
36
37
38 LttEvent *ltt_event_new()
39 {
40 return g_new(LttEvent, 1);
41 }
42
43 void ltt_event_destroy(LttEvent *event)
44 {
45 g_free(event);
46 }
47
48
49 /*****************************************************************************
50 *Function name
51 * ltt_event_refresh_fields : refresh fields of an event
52 *Input params
53 * offsetRoot : offset from the root
54 * offsetParent : offset from the parent
55 * fld : field
56 * evD : event data
57 * reverse_byte_order : 1 or 0
58 *Return value
59 * int : size of the field
60 ****************************************************************************/
61
62 int ltt_event_refresh_fields(int offsetRoot,int offsetParent,
63 LttField * fld, void *evD, gboolean reverse_byte_order)
64 {
65 int size, size1, element_number, i, offset1, offset2;
66 LttType * type = fld->field_type;
67
68 switch(type->type_class) {
69 case LTT_ARRAY:
70 element_number = (int) type->element_number;
71 if(fld->field_fixed == 0){// has string or sequence
72 size = 0;
73 for(i=0;i<element_number;i++){
74 size += ltt_event_refresh_fields(offsetRoot+size,size,
75 fld->child[0], evD+size, reverse_byte_order);
76 }
77 }else size = fld->field_size;
78 break;
79
80 case LTT_SEQUENCE:
81 size1 = fld->sequ_number_size;
82 element_number = getIntNumber(reverse_byte_order,size1,evD);
83 type->element_number = element_number;
84 if(fld->element_size > 0){
85 size = element_number * fld->element_size;
86 }else{//sequence has string or sequence
87 size = 0;
88 for(i=0;i<element_number;i++){
89 size += ltt_event_refresh_fields(offsetRoot+size+size1,size+size1,
90 fld->child[0], evD+size+size1, reverse_byte_order);
91 }
92 size += size1;
93 }
94 break;
95
96 case LTT_STRING:
97 size = strlen((gchar*)evD) + 1; //include end : '\0'
98 break;
99
100 case LTT_STRUCT:
101 element_number = (int) type->element_number;
102 if(fld->field_fixed == 0){
103 offset1 = offsetRoot;
104 offset2 = 0;
105 for(i=0;i<element_number;i++){
106 size=ltt_event_refresh_fields(offset1,offset2,
107 fld->child[i],evD+offset2, reverse_byte_order);
108 offset1 += size;
109 offset2 += size;
110 }
111 size = offset2;
112 }else size = fld->field_size;
113 break;
114
115 case LTT_UNION:
116 size = fld->field_size;
117 break;
118
119 default:
120 size = fld->field_size;
121 }
122
123 #if 0
124 if(type->type_class != LTT_STRUCT && type->type_class != LTT_ARRAY &&
125 type->type_class != LTT_SEQUENCE && type->type_class != LTT_STRING){
126 size = fld->field_size;
127 }else if(type->type_class == LTT_ARRAY){
128 element_number = (int) type->element_number;
129 if(fld->field_fixed == 0){// has string or sequence
130 size = 0;
131 for(i=0;i<element_number;i++){
132 size += ltt_event_refresh_fields(offsetRoot+size,size,
133 fld->child[0], evD+size);
134 }
135 }else size = fld->field_size;
136 }else if(type->type_class == LTT_SEQUENCE){
137 size1 = fld->sequ_number_size;
138 element_number = getIntNumber(size1,evD);
139 type->element_number = element_number;
140 if(fld->element_size > 0){
141 size = element_number * fld->element_size;
142 }else{//sequence has string or sequence
143 size = 0;
144 for(i=0;i<element_number;i++){
145 size += ltt_event_refresh_fields(offsetRoot+size+size1,size+size1,
146 fld->child[0], evD+size+size1);
147 }
148 size += size1;
149 }
150 }else if(type->type_class == LTT_STRING){
151 size = strlen((char*)evD) + 1; //include end : '\0'
152 }else if(type->type_class == LTT_STRUCT){
153 element_number = (int) type->element_number;
154 if(fld->field_fixed == 0){
155 offset1 = offsetRoot;
156 offset2 = 0;
157 for(i=0;i<element_number;i++){
158 size=ltt_event_refresh_fields(offset1,offset2,
159 fld->child[i],evD+offset2);
160 offset1 += size;
161 offset2 += size;
162 }
163 size = offset2;
164 }else size = fld->field_size;
165 }
166 #endif //0
167 fld->offset_root = offsetRoot;
168 fld->offset_parent = offsetParent;
169 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
170 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
171 fld->field_size = size;
172
173 return size;
174 }
175
176 /*****************************************************************************
177 *Function name
178 * ltt_event_eventtype_id: get event type id
179 * (base id + position of the event)
180 *Input params
181 * e : an instance of an event type
182 *Return value
183 * unsigned : event type id
184 ****************************************************************************/
185
186 unsigned ltt_event_eventtype_id(LttEvent *e)
187 {
188 return (unsigned) e->event_id;
189 }
190
191 /*****************************************************************************
192 *Function name
193 * ltt_event_facility : get the facility of the event
194 *Input params
195 * e : an instance of an event type
196 *Return value
197 * LttFacility * : the facility of the event
198 ****************************************************************************/
199
200 LttFacility *ltt_event_facility(LttEvent *e)
201 {
202 LttTrace * trace = e->tracefile->trace;
203 unsigned id = e->event_id;
204 return ltt_trace_facility_by_id(trace,id);
205 }
206
207 /*****************************************************************************
208 *Function name
209 * ltt_event_eventtype : get the event type of the event
210 *Input params
211 * e : an instance of an event type
212 *Return value
213 * LttEventType * : the event type of the event
214 ****************************************************************************/
215
216 LttEventType *ltt_event_eventtype(LttEvent *e)
217 {
218 LttFacility* facility = ltt_event_facility(e);
219 if(!facility) return NULL;
220 return facility->events[e->event_id - facility->base_id];
221 }
222
223 /*****************************************************************************
224 *Function name
225 * ltt_event_field : get the root field of the event
226 *Input params
227 * e : an instance of an event type
228 *Return value
229 * LttField * : the root field of the event
230 ****************************************************************************/
231
232 LttField *ltt_event_field(LttEvent *e)
233 {
234 LttField * field;
235 LttEventType * event_type = ltt_event_eventtype(e);
236 if(unlikely(!event_type)) return NULL;
237 field = event_type->root_field;
238 if(unlikely(!field)) return NULL;
239
240 //check if the field need refresh
241 if(likely(e->which_block != event_type->latest_block ||
242 e->which_event != event_type->latest_event)){
243
244 event_type->latest_block = e->which_block;
245 event_type->latest_event = e->which_event;
246
247 if(unlikely(field->field_fixed != 1))
248 ltt_event_refresh_fields(0, 0, field, e->data,
249 e->tracefile->trace->reverse_byte_order);
250 }
251 return field;
252 }
253
254 /*****************************************************************************
255 *Function name
256 * ltt_event_time : get the time of the event
257 *Input params
258 * e : an instance of an event type
259 *Return value
260 * LttTime : the time of the event
261 ****************************************************************************/
262
263 LttTime ltt_event_time(LttEvent *e)
264 {
265 return e->event_time;
266 }
267
268 /*****************************************************************************
269 *Function name
270 * ltt_event_time : get the cycle count of the event
271 *Input params
272 * e : an instance of an event type
273 *Return value
274 * LttCycleCount : the cycle count of the event
275 ****************************************************************************/
276
277 LttCycleCount ltt_event_cycle_count(LttEvent *e)
278 {
279 return e->event_cycle_count;
280 }
281
282 /*****************************************************************************
283 *Function name
284 * ltt_event_position : get the event's position
285 *Input params
286 * e : an instance of an event type
287 * ep : a pointer to event's position structure
288 ****************************************************************************/
289
290 void ltt_event_position(LttEvent *e, LttEventPosition *ep)
291 {
292 ep->block_num = e->which_block;
293 ep->event_num = e->which_event;
294 ep->event_time = e->event_time;
295 ep->event_cycle_count = e->event_cycle_count;
296 ep->heart_beat_number = e->tracefile->cur_heart_beat_number;
297 ep->old_position = TRUE;
298 ep->event_offset = e->data - e->tracefile->buffer - EVENT_HEADER_SIZE ;
299 ep->tf = e->tracefile;
300 ep->overflow_nsec = e->overflow_nsec;
301 /* This is a workaround for fast position seek */
302 ep->last_event_pos = e->last_event_pos;
303 ep->prev_block_end_time = e->prev_block_end_time;
304 ep->prev_event_time = e->prev_event_time;
305 ep->pre_cycle_count = e->pre_cycle_count;
306 ep->count = e->count;
307 ep->last_heartbeat = e->last_heartbeat;
308
309 /* end of workaround */
310 }
311
312 LttEventPosition * ltt_event_position_new()
313 {
314 return g_new(LttEventPosition, 1);
315 }
316
317 /*****************************************************************************
318 *Function name
319 * ltt_event_position_get : get the block number and index of the event
320 *Input params
321 * ep : a pointer to event's position structure
322 * block_number : the block number of the event
323 * index_in_block : the index of the event within the block
324 ****************************************************************************/
325
326 void ltt_event_position_get(LttEventPosition *ep,
327 unsigned *block_number, unsigned *index_in_block, LttTracefile ** tf)
328 {
329 *block_number = ep->block_num;
330 *index_in_block = ep->event_num;
331 *tf = ep->tf;
332 }
333
334 /*****************************************************************************
335 *Function name
336 * ltt_event_position_set : set the block number and index of the event
337 * It does put the old_position gboolean to FALSE, as it is impossible
338 * to know the quick position to seek in the tracefile.
339 *Input params
340 * ep : a pointer to event's position structure
341 * block_number : the block number of the event
342 * index_in_block : the index of the event within the block
343 ****************************************************************************/
344
345 void ltt_event_position_set(LttEventPosition *ep,
346 unsigned block_number, unsigned index_in_block)
347 {
348 if(ep->block_num != block_number || ep->event_num != index_in_block)
349 ep->old_position = FALSE;
350
351 ep->block_num = block_number;
352 ep->event_num = index_in_block;
353
354 }
355
356 /*****************************************************************************
357 * Function name
358 * ltt_event_position_compare : compare two positions
359 * A NULL value is infinite.
360 * Input params
361 * ep1 : a pointer to event's position structure
362 * ep2 : a pointer to event's position structure
363 * Return
364 * -1 is ep1 < ep2
365 * 1 if ep1 > ep2
366 * 0 if ep1 == ep2
367 ****************************************************************************/
368
369
370 gint ltt_event_position_compare(const LttEventPosition *ep1,
371 const LttEventPosition *ep2)
372 {
373 if(ep1->tf != ep2->tf)
374 g_error("ltt_event_position_compare on different tracefiles makes no sense");
375 if(ep1 == NULL && ep2 == NULL)
376 return 0;
377 if(ep1 != NULL && ep2 == NULL)
378 return -1;
379 if(ep1 == NULL && ep2 != NULL)
380 return 1;
381
382 if(ep1->block_num < ep2->block_num)
383 return -1;
384 if(ep1->block_num > ep2->block_num)
385 return 1;
386 if(ep1->event_num < ep2->event_num)
387 return -1;
388 if(ep1->event_num > ep2->event_num)
389 return 1;
390 return 0;
391 }
392
393 /*****************************************************************************
394 * Function name
395 * ltt_event_event_position_compare : compare two positions, one in event,
396 * other in position opaque structure.
397 * Input params
398 * event : a pointer to event structure
399 * ep : a pointer to event's position structure
400 * Return
401 * -1 is event < ep
402 * 1 if event > ep
403 * 0 if event == ep
404 ****************************************************************************/
405
406 gint ltt_event_event_position_compare(const LttEvent *event,
407 const LttEventPosition *ep)
408 {
409 if(event == NULL && ep == NULL)
410 return 0;
411 if(event != NULL && ep == NULL)
412 return -1;
413 if(event == NULL && ep != NULL)
414 return 1;
415
416 g_assert(event->tracefile == ep->tf);
417
418 if(event->which_block < ep->block_num)
419 return -1;
420 if(event->which_block > ep->block_num)
421 return 1;
422 if(event->which_event < ep->event_num)
423 return -1;
424 if(event->which_event > ep->event_num)
425 return 1;
426 return 0;
427 }
428
429 /*****************************************************************************
430 * Function name
431 * ltt_event_position_copy : copy position
432 * Input params
433 * src : a pointer to event's position structure source
434 * dest : a pointer to event's position structure dest
435 * Return
436 * void
437 ****************************************************************************/
438 void ltt_event_position_copy(LttEventPosition *dest,
439 const LttEventPosition *src)
440 {
441 if(src == NULL)
442 dest = NULL;
443 else
444 *dest = *src;
445 }
446
447
448 /*****************************************************************************
449 *Function name
450 * ltt_event_cpu_i: get the cpu id where the event happens
451 *Input params
452 * e : an instance of an event type
453 *Return value
454 * unsigned : the cpu id
455 ****************************************************************************/
456
457 unsigned ltt_event_cpu_id(LttEvent *e)
458 {
459 gchar * c1, * c2, * c3;
460 c1 = strrchr(e->tracefile->name,'\\');
461 c2 = strrchr(e->tracefile->name,'/');
462 if(c1 == NULL && c2 == NULL){
463 return (unsigned)atoi(e->tracefile->name);
464 }else if(c1 == NULL){
465 c2++;
466 return (unsigned)atoi(c2);
467 }else if(c2 == NULL){
468 c1++;
469 return (unsigned)atoi(c1);
470 }else{
471 c3 = (c1 > c2) ? c1 : c2;
472 c3++;
473 return (unsigned)atoi(c3);
474 }
475 }
476
477 /*****************************************************************************
478 *Function name
479 * ltt_event_data : get the raw data for the event
480 *Input params
481 * e : an instance of an event type
482 *Return value
483 * void * : pointer to the raw data for the event
484 ****************************************************************************/
485
486 void *ltt_event_data(LttEvent *e)
487 {
488 return e->data;
489 }
490
491 /*****************************************************************************
492 *Function name
493 * ltt_event_field_element_number
494 * : The number of elements in a sequence field is specific
495 * to each event. This function returns the number of
496 * elements for an array or sequence field in an event.
497 *Input params
498 * e : an instance of an event type
499 * f : a field of the instance
500 *Return value
501 * unsigned : the number of elements for an array/sequence field
502 ****************************************************************************/
503
504 unsigned ltt_event_field_element_number(LttEvent *e, LttField *f)
505 {
506 if(f->field_type->type_class != LTT_ARRAY &&
507 f->field_type->type_class != LTT_SEQUENCE)
508 return 0;
509
510 if(f->field_type->type_class == LTT_ARRAY)
511 return f->field_type->element_number;
512 return (unsigned) getIntNumber(e->tracefile->trace->reverse_byte_order,
513 f->sequ_number_size, e + f->offset_root);
514 }
515
516 /*****************************************************************************
517 *Function name
518 * ltt_event_field_element_select
519 * : Set the currently selected element for a sequence or
520 * array field
521 *Input params
522 * e : an instance of an event type
523 * f : a field of the instance
524 * i : the ith element
525 ****************************************************************************/
526
527 void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i)
528 {
529 unsigned element_number;
530 LttField *fld;
531 unsigned int k;
532 int size;
533 void *evD;
534
535 if(f->field_type->type_class != LTT_ARRAY &&
536 f->field_type->type_class != LTT_SEQUENCE)
537 return ;
538
539 element_number = ltt_event_field_element_number(e,f);
540 /* Sanity check for i : 1..n only, and must be lower or equal element_number
541 */
542 if(element_number < i || i == 0) return;
543
544 fld = f->child[0];
545
546 evD = e->data + f->offset_root;
547 size = 0;
548 for(k=0;k<i;k++){
549 size += ltt_event_refresh_fields(f->offset_root+size,size, fld, evD+size,
550 e->tracefile->trace->reverse_byte_order);
551 }
552 f->current_element = i - 1;
553 }
554
555 /*****************************************************************************
556 * These functions extract data from an event after architecture specific
557 * conversions
558 ****************************************************************************/
559
560 guint32 ltt_event_get_unsigned(LttEvent *e, LttField *f)
561 {
562 //int revFlag = e->tracefile->trace->my_arch_endian ==
563 // e->tracefile->trace->system_description->endian ? 0:1;
564 gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order;
565
566 LttTypeEnum t = f->field_type->type_class;
567
568 g_assert(t == LTT_UINT || t == LTT_ENUM);
569
570 if(f->field_size == 1){
571 guint8 x = *(guint8 *)(e->data + f->offset_root);
572 return (guint32) x;
573 }else if(f->field_size == 2){
574 return (guint32)ltt_get_uint16(reverse_byte_order, e->data + f->offset_root);
575 }else if(f->field_size == 4){
576 return (guint32)ltt_get_uint32(reverse_byte_order, e->data + f->offset_root);
577 }
578 #if 0
579 else if(f->field_size == 8){
580 guint64 x = *(guint64 *)(e->data + f->offset_root);
581 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
582 return (unsigned int) (revFlag ? GUINT64_FROM_BE(x): x);
583 else
584 return (unsigned int) (revFlag ? GUINT64_FROM_LE(x): x);
585 }
586 #endif //0
587 g_critical("ltt_event_get_unsigned : field size %i unknown", f->field_size);
588 return 0;
589 }
590
591 gint32 ltt_event_get_int(LttEvent *e, LttField *f)
592 {
593 gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order;
594 //int revFlag = e->tracefile->trace->my_arch_endian ==
595 // e->tracefile->trace->system_description->endian ? 0:1;
596
597 g_assert(f->field_type->type_class == LTT_INT);
598
599 if(f->field_size == 1){
600 gint8 x = *(gint8 *)(e->data + f->offset_root);
601 return (gint32) x;
602 }else if(f->field_size == 2){
603 return (gint32)ltt_get_int16(reverse_byte_order, e->data + f->offset_root);
604 }else if(f->field_size == 4){
605 return (gint32)ltt_get_int32(reverse_byte_order, e->data + f->offset_root);
606 }
607 #if 0
608 else if(f->field_size == 8){
609 gint64 x = *(gint64 *)(e->data + f->offset_root);
610 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
611 return (int) (revFlag ? GINT64_FROM_BE(x): x);
612 else
613 return (int) (revFlag ? GINT64_FROM_LE(x): x);
614 }
615 #endif //0
616 g_critical("ltt_event_get_int : field size %i unknown", f->field_size);
617 return 0;
618 }
619
620 guint64 ltt_event_get_long_unsigned(LttEvent *e, LttField *f)
621 {
622 gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order;
623 //int revFlag = e->tracefile->trace->my_arch_endian ==
624 // e->tracefile->trace->system_description->endian ? 0:1;
625 LttTypeEnum t = f->field_type->type_class;
626
627 g_assert(t == LTT_UINT || t == LTT_ENUM);
628
629 if(f->field_size == 1){
630 guint8 x = *(guint8 *)(e->data + f->offset_root);
631 return (guint64) x;
632 }else if(f->field_size == 2){
633 return (guint64)ltt_get_uint16(reverse_byte_order, e->data + f->offset_root);
634 }else if(f->field_size == 4){
635 return (guint64)ltt_get_uint32(reverse_byte_order, e->data + f->offset_root);
636 }else if(f->field_size == 8){
637 return ltt_get_uint64(reverse_byte_order, e->data + f->offset_root);
638 }
639 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f->field_size);
640 return 0;
641 }
642
643 gint64 ltt_event_get_long_int(LttEvent *e, LttField *f)
644 {
645 //int revFlag = e->tracefile->trace->my_arch_endian ==
646 // e->tracefile->trace->system_description->endian ? 0:1;
647 gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order;
648
649 g_assert( f->field_type->type_class == LTT_INT);
650
651 if(f->field_size == 1){
652 gint8 x = *(gint8 *)(e->data + f->offset_root);
653 return (gint64) x;
654 }else if(f->field_size == 2){
655 return (gint64)ltt_get_int16(reverse_byte_order, e->data + f->offset_root);
656 }else if(f->field_size == 4){
657 return (gint64)ltt_get_int32(reverse_byte_order, e->data + f->offset_root);
658 }else if(f->field_size == 8){
659 return ltt_get_int64(reverse_byte_order, e->data + f->offset_root);
660 }
661 g_critical("ltt_event_get_long_int : field size %i unknown", f->field_size);
662 return 0;
663 }
664
665 float ltt_event_get_float(LttEvent *e, LttField *f)
666 {
667 //int revFlag = e->tracefile->trace->my_arch_endian ==
668 // e->tracefile->trace->system_description->endian ? 0:1;
669 gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order;
670
671 g_assert(f->field_type->type_class == LTT_FLOAT && f->field_size == 4);
672
673 if(reverse_byte_order == 0) return *(float *)(e->data + f->offset_root);
674 else{
675 guint32 aInt;
676 memcpy((void*)&aInt, e->data + f->offset_root, 4);
677 aInt = ___swab32(aInt);
678 return ((float)aInt);
679 }
680 }
681
682 double ltt_event_get_double(LttEvent *e, LttField *f)
683 {
684 gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order;
685 //int revFlag = e->tracefile->trace->my_arch_endian ==
686 // e->tracefile->trace->system_description->endian ? 0:1;
687
688 g_assert(f->field_type->type_class == LTT_FLOAT && f->field_size == 8);
689
690 if(reverse_byte_order == 0) return *(double *)(e->data + f->offset_root);
691 else{
692 guint64 aInt;
693 memcpy((void*)&aInt, e->data + f->offset_root, 8);
694 aInt = ___swab64(aInt);
695 return ((double)aInt);
696 }
697 }
698
699 /*****************************************************************************
700 * The string obtained is only valid until the next read from
701 * the same tracefile.
702 ****************************************************************************/
703
704 char *ltt_event_get_string(LttEvent *e, LttField *f)
705 {
706 g_assert(f->field_type->type_class == LTT_STRING);
707
708 return (gchar*)g_strdup((gchar*)(e->data + f->offset_root));
709 }
This page took 0.046483 seconds and 4 git commands to generate.