first version of reading api source files
[lttv.git] / ltt / branches / poly / ltt / tracefile.c
1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <sys/stat.h>
4 #include <sys/types.h>
5 #include <linux/errno.h>
6
7 #include "LTTTypes.h"
8 #include "parser.h"
9 #include <ltt/tracefile.h>
10
11 #include "default.h" //yxx test
12
13 /* set the offset of the fields belonging to the event,
14 need the information of the archecture */
15 void setFieldsOffset(ltt_tracefile * t, ltt_eventtype *evT, void *evD);
16
17 /* get the size of the field type according to the archtecture's
18 size and endian type(info of the archecture) */
19 int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot,
20 int offsetParent, ltt_field * fld, void * evD );
21
22 /* read a fixed size or a block information from the file (fd) */
23 int readFile(int fd, void * buf, size_t size, char * mesg);
24 int readBlock(ltt_tracefile * tf, int whichBlock);
25
26 /* calculate cycles per nsec for current block */
27 void getCyclePerNsec(ltt_tracefile * t);
28
29 /* functions to release the memory occupied by the tables of a tracefile */
30 void freeKey (gpointer key, gpointer value, gpointer user_data);
31 void freeValue (gpointer key, gpointer value, gpointer user_data);
32 void freeFacilityNameTable (gpointer key, gpointer value, gpointer user_data);
33
34 /* reinitialize the info of the block which is already in the buffer */
35 void updateTracefile(ltt_tracefile * tf);
36
37 /* go to the next event */
38 int skipEvent(ltt_tracefile * t);
39
40 /* compare two time (ltt_time), 0:t1=t2, -1:t1<t2, 1:t1>t2 */
41 int timecmp(ltt_time * t1, ltt_time * t2);
42
43 /* get an integer number */
44 int getIntNumber(int size1, void *evD);
45
46
47 /* Time operation macros for ltt_time (struct timespec) */
48 /* (T3 = T2 - T1) */
49 #define TimeSub(T3, T2, T1) \
50 do \
51 {\
52 (T3).tv_sec = (T2).tv_sec - (T1).tv_sec; \
53 (T3).tv_nsec = (T2).tv_nsec - (T1).tv_nsec; \
54 if((T3).tv_nsec < 0)\
55 {\
56 (T3).tv_sec--;\
57 (T3).tv_nsec += 1000000000;\
58 }\
59 } while(0)
60
61 /* (T3 = T2 + T1) */
62 #define TimeAdd(T3, T2, T1) \
63 do \
64 {\
65 (T3).tv_sec = (T2).tv_sec + (T1).tv_sec; \
66 (T3).tv_nsec = (T2).tv_nsec + (T1).tv_nsec; \
67 if((T3).tv_nsec >= 1000000000)\
68 {\
69 (T3).tv_sec += (T3).tv_nsec / 1000000000;\
70 (T3).tv_nsec = (T3).tv_nsec % 1000000000;\
71 }\
72 } while(0)
73
74
75
76 /*****************************************************************************
77 *Function name
78 * ltt_tracefile_open : open a trace file, construct a ltt_tracefile
79 *Input params
80 * pathname : path name of the trace file
81 *Return value
82 * ltt_tracefile * : the structure represents the opened trace file
83 ****************************************************************************/
84
85 ltt_tracefile *ltt_tracefile_open(char * fileName)
86 {
87 ltt_tracefile * tf;
88 struct stat lTDFStat; /* Trace data file status */
89 trace_header_event *trace_header;
90 block_header a_block_header;
91
92 tf = g_new(ltt_tracefile, 1);
93
94 //open the file
95 tf->fd = open(fileName, O_RDONLY, 0);
96 if(tf->fd < 0){
97 g_error("Unable to open input data file %s\n", fileName);
98 }
99
100 // Get the file's status
101 if(fstat(tf->fd, &lTDFStat) < 0){
102 g_error("Unable to get the status of the input data file %s\n", fileName);
103 }
104
105 // Is the file large enough to contain a trace
106 if(lTDFStat.st_size < sizeof(block_header) + sizeof(trace_header_event)){
107 g_error("The input data file %s does not contain a trace\n", fileName);
108 }
109
110 //store the size of the file
111 tf->file_size = lTDFStat.st_size;
112
113 //read the first block header
114 if(readFile(tf->fd,(void*)&a_block_header, sizeof(block_header),
115 "Unable to read block header"))
116 exit(1);
117
118 //read the trace header event
119 trace_header = g_new(trace_header_event, 1);
120 if(readFile(tf->fd,(void*)trace_header, sizeof(trace_header_event),
121 "Unable to read trace header event"))
122 exit(1);
123
124 tf->block_number = tf->file_size / trace_header->buffer_size;
125 tf->trace_header = (trace_header_event *)trace_header;
126
127 //allocate memory to contain the info of a block
128 tf->buffer = (void *) g_new(char, trace_header->buffer_size);
129
130 //read the last block, get the trace end time
131 if(readBlock(tf,tf->block_number)) exit(1);
132 tf->end_time = tf->a_block_footer->time;
133
134 //read the first block, get the trace start time
135 if(tf->block_number != 1)
136 if(readBlock(tf,1)) exit(1);
137 tf->start_time = tf->a_block_header->time;
138
139 //get local machine's data type size and endian type
140 getDataEndianType(&(tf->my_arch_size), &(tf->my_arch_endian));
141
142 //initialize all tables
143 tf->eventtype_number = 0;
144 tf->facility_number = 0;
145 tf->index_facility = g_hash_table_new (g_int_hash, g_int_equal);
146 tf->facility_name = g_hash_table_new (g_str_hash, g_str_equal);
147 tf->base_id_name = g_hash_table_new (g_str_hash, g_int_equal);
148 tf->eventtype_event_id = g_ptr_array_new();
149
150 return tf;
151 }
152
153 /*****************************************************************************
154 *Function name
155 * ltt_tracefile_close: close a trace file, release all facilities if their
156 * usage count == 0 when close_facilities is true
157 *Input params
158 * t : tracefile which will be closed
159 * close_facilities : bool to show if the facilities need to be released
160 *Return value
161 * int : ????
162 ****************************************************************************/
163
164 int ltt_tracefile_close(ltt_tracefile *t, int close_facilities)
165 {
166 //free index_facility table
167 g_hash_table_foreach (t->index_facility, freeKey, NULL);
168 g_hash_table_destroy(t->index_facility);
169
170 //free base_id_facility table
171 g_hash_table_foreach (t->base_id_name, freeValue, NULL);
172 g_hash_table_destroy(t->base_id_name);
173
174 //free eventtype_event_id array
175 g_ptr_array_free (t->eventtype_event_id, TRUE);
176
177 //free facility_name table
178 g_hash_table_foreach (t->facility_name, freeFacilityNameTable,
179 GINT_TO_POINTER(1));
180 g_hash_table_destroy(t->facility_name);
181
182 //free tracefile structure
183 g_free(t->trace_header);
184 g_free(t->buffer);
185 g_free(t);
186 return 0;
187 }
188
189 /*****************************************************************************
190 * functions to release the memory occupied by the tables of a tracefile
191 ****************************************************************************/
192
193 void freeKey (gpointer key, gpointer value, gpointer user_data)
194 {
195 g_free(key);
196 }
197
198 void freeValue (gpointer key, gpointer value, gpointer user_data)
199 {
200 g_free(value);
201 }
202
203 void freeFacilityNameTable (gpointer key, gpointer value, gpointer user_data)
204 {
205 ltt_facility * fac = (ltt_facility*) value;
206 fac->usage_count--;
207 if(GPOINTER_TO_INT(user_data) != 0)
208 ltt_facility_close(fac);
209 }
210
211 /*****************************************************************************
212 *Function name
213 * ltt_tracefile_facility_add: increases the facility usage count and also
214 * specifies the base of the numeric range
215 * assigned to the event types in the facility
216 * for this tracefile
217 *Input params
218 * t : tracefile that the facility will be added
219 * f : facility that will be attached to the tracefile
220 * base_id : the id for the first event of the facility in the
221 * trace file
222 *Return value
223 * int : ????
224 ****************************************************************************/
225
226 int ltt_tracefile_facility_add(ltt_tracefile *t,ltt_facility *f,int base_id)
227 {
228 int * id, *index;
229 int i, j, k;
230 ltt_eventtype * et;
231 gpointer tmpPtr;
232
233 //increase the facility usage count
234 f->usage_count++;
235 t->eventtype_number += f->event_number;
236 t->facility_number++;
237
238 //insert the facility into index_facility table
239 id = g_new(int,1);
240 *id = t->facility_number;
241 g_hash_table_insert(t->index_facility, (gpointer)id,(gpointer)f);
242
243 //insert facility name into table: base_id_name
244 id = g_new(int,1);
245 *id = base_id;
246 g_hash_table_insert(t->base_id_name, (gpointer)(f->name), (gpointer)id);
247
248 //insert facility name into table: facility_name
249 g_hash_table_insert(t->facility_name, (gpointer)(f->name), (gpointer)f);
250
251 //insert eventtype into the array: eventtype_event_id
252 j = base_id + f->event_number;
253 k = t->eventtype_event_id->len;
254 if(j > t->eventtype_event_id->len){
255 for(i=0; i < j - k; i++){
256 tmpPtr = (gpointer)g_new(ptr_wrap, 1);
257 g_ptr_array_add(t->eventtype_event_id,tmpPtr);
258 }
259 }
260
261 //initialize the unused elements: NULL
262 if(j-k > f->event_number){
263 for(i=k; i<base_id; i++){
264 tmpPtr = g_ptr_array_index(t->eventtype_event_id, i);
265 ((ptr_wrap*)tmpPtr)->ptr = NULL;
266 }
267 }
268
269 //initialize the elements with the eventtypes belonging to the facility
270 for(i=0; i<f->event_number; i++){
271 tmpPtr = g_ptr_array_index(t->eventtype_event_id, base_id + i);
272 ((ptr_wrap*)tmpPtr)->ptr = (gpointer)(f->events[i]);
273 }
274
275 //update offset
276 for(i=0; i<f->event_number; i++){
277 et = f->events[i];
278 setFieldsOffset(t, et, NULL);
279 }
280
281
282 return 0;
283 }
284
285 /*****************************************************************************
286 * The following functions used to query the info of the machine where the
287 * tracefile was generated. A tracefile may be queried for its architecture
288 * type(e.g.,"i386", "powerpc", "powerpcle", "s390", "s390x"), its architecture
289 * variant(e.g., "att" versus "sun" for m68k), its operating system (e.g.,
290 * "linux","bsd"), its generic architecture, and the machine identity (e.g.,
291 * system host name). All character strings belong to the associated tracefile
292 * and are freed when it is closed
293 ****************************************************************************/
294
295 uint32_t ltt_tracefile_arch_type(ltt_tracefile *t)
296 {
297 return t->trace_header->arch_type;
298 }
299
300 uint32_t ltt_tracefile_arch_variant(ltt_tracefile *t)
301 {
302 return t->trace_header->arch_variant;
303 }
304
305 ltt_arch_size ltt_tracefile_arch_size(ltt_tracefile *t)
306 {
307 return t->trace_header->arch_size;
308 }
309
310 ltt_arch_endian ltt_tracefile_arch_endian(ltt_tracefile *t)
311 {
312 return t->trace_header->arch_endian;
313 }
314
315 uint32_t ltt_tracefile_system_type(ltt_tracefile *t)
316 {
317 return t->trace_header->system_type;
318 }
319
320 char *ltt_tracefile_system_name(ltt_tracefile *t)
321 {
322 return t->trace_header->system_name;
323 }
324
325 /*****************************************************************************
326 *Function name
327 * ltt_tracefile_cpu_number: get the number of the cpu
328 *Input params
329 * t : tracefile
330 *Return value
331 * unsigned : the number of cpu the system has
332 ****************************************************************************/
333
334 unsigned ltt_tracefile_cpu_number(ltt_tracefile *t)
335 {
336 return (unsigned)(t->trace_header->cpu_number);
337 }
338
339 /*****************************************************************************
340 *Function name
341 * ltt_tracefile_cpu_single: does the tracefile contain events only for a
342 * single CPU ?
343 *Input params
344 * t : tracefile
345 *Return value
346 * int : 1 for YES, 0 for NO
347 ****************************************************************************/
348
349 int ltt_tracefile_cpu_single(ltt_tracefile *t)
350 {
351 if(t->trace_header->cpu_number_used == 1) return 1;
352 else return 0;
353 }
354
355 /*****************************************************************************
356 *Function name
357 * ltt_tracefile_cpu_id: which CPU is contained in the tracefile?
358 *Input params
359 * t : tracefile
360 *Return value
361 * unsigned : cpu id
362 ****************************************************************************/
363
364 unsigned ltt_tracefile_cpu_id(ltt_tracefile *t)
365 {
366 return (unsigned)(t->trace_header->cpu_id);
367 }
368
369 /*****************************************************************************
370 * The following functions get the times related to the tracefile
371 ****************************************************************************/
372
373 ltt_time ltt_tracefile_time_start(ltt_tracefile *t)
374 {
375 return t->start_time;
376 }
377
378 ltt_time ltt_tracefile_time_end(ltt_tracefile *t)
379 {
380 return t->end_time;
381 }
382
383 ltt_time ltt_tracefile_duration(ltt_tracefile *t)
384 {
385 ltt_time T;
386 TimeSub(T, t->end_time, t->start_time);
387 return T;
388 }
389
390 /*****************************************************************************
391 * The following functions discover the facilities added to the tracefile
392 ****************************************************************************/
393
394 unsigned ltt_tracefile_facility_number(ltt_tracefile *t)
395 {
396 return (unsigned)(t->facility_number);
397 }
398
399 ltt_facility *ltt_tracefile_facility_get(ltt_tracefile *t, unsigned i)
400 {
401 gconstpointer ptr = (gconstpointer)(&i);
402 if(i<=0 || i> t->facility_number)return NULL;
403 return (ltt_facility*)g_hash_table_lookup(t->index_facility,ptr);
404 }
405
406 ltt_facility *ltt_tracefile_facility_get_by_name(ltt_tracefile *t,char *name)
407 {
408 ltt_facility * fac;
409 fac=(ltt_facility*)g_hash_table_lookup(t->facility_name,(gconstpointer)name);
410 return fac;
411 }
412
413 /*****************************************************************************
414 * The following functions to discover all the event types in the facilities
415 * added to the tracefile. The event type integer id, unique for the trace,
416 * is used
417 ****************************************************************************/
418
419 unsigned ltt_tracefile_eventtype_number(ltt_tracefile *t)
420 {
421 return t->eventtype_number;
422 }
423
424 ltt_eventtype *ltt_tracefile_eventtype_get(ltt_tracefile *t, unsigned evId)
425 {
426 ptr_wrap * ptr;
427 ptr = (ptr_wrap *)g_ptr_array_index(t->eventtype_event_id, (gint)evId);
428 return (ltt_eventtype *)(ptr->ptr);
429 }
430
431 /*****************************************************************************
432 *Function name
433 * ltt_tracefile_eventtype_id
434 * : given an event type, find its unique id within
435 * the tracefile
436 *Input params
437 * t : tracefile
438 * et : event type
439 *Return value
440 * unsigned : id of the event type in the tracefile
441 ****************************************************************************/
442
443 unsigned ltt_tracefile_eventtype_id(ltt_tracefile *t, ltt_eventtype *et)
444 {
445 int *id;
446 char *name = et->facility->name;
447
448 id = (int*)g_hash_table_lookup(t->base_id_name, (gconstpointer)name);
449 if(!id)return 0;
450 return (unsigned)(*id + et->index);
451 }
452
453 /*****************************************************************************
454 *Function name
455 * ltt_tracefile_eventtype_root_field
456 * : get the root field associated with an event type
457 * for the tracefile
458 *Input params
459 * t : tracefile
460 * id : event id
461 *Return value
462 * ltt_field * : root field of the event
463 ****************************************************************************/
464
465 ltt_field *ltt_tracefile_eventtype_root_field(ltt_tracefile *t, unsigned id)
466 {
467 ltt_eventtype * et;
468 et = ltt_tracefile_eventtype_get(t, id);
469 if(!et) return NULL;
470 return et->root_field;
471 }
472
473 /*****************************************************************************
474 *Function name
475 * ltt_tracefile_seek_time: seek to the first event of the trace with time
476 * larger or equal to time
477 *Input params
478 * t : tracefile
479 * time : criteria of the time
480 *Return value
481 * int : error code
482 * ENOENT, end of the file
483 * EINVAL, lseek fail
484 * EIO, can not read from the file
485 ****************************************************************************/
486
487 int ltt_tracefile_seek_time(ltt_tracefile *t, ltt_time time)
488 {
489 int err;
490 ltt_time lttTime;
491 int headTime = timecmp(&(t->a_block_header->time), &time);
492 int tailTime = timecmp(&(t->a_block_footer->time), &time);
493
494 if(headTime < 0 && tailTime > 0){
495 lttTime = getEventTime(t);
496 err = timecmp(&lttTime, &time);
497 if(err >= 0){
498 if( ( (t->which_block != 1 && t->which_event != 0) ||
499 (t->which_block == 1 && t->which_event != 1) ) &&
500 ((t->prev_event_time.tv_sec==0 && t->prev_event_time.tv_nsec==0) ||
501 timecmp(&t->prev_event_time, &time) >= 0 ) ){
502 updateTracefile(t);
503 return ltt_tracefile_seek_time(t, time);
504 }
505 }else if(err < 0){
506 err = t->which_block;
507 if(ltt_tracefile_read(t) == NULL) return ENOENT;
508 if(t->which_block == err)
509 return ltt_tracefile_seek_time(t,time);
510 }
511 }else if(headTime > 0){
512 if(t->which_block == 1){
513 updateTracefile(t);
514 }else{
515 if( (t->prev_block_end_time.tv_sec == 0 &&
516 t->prev_block_end_time.tv_nsec == 0 ) ||
517 timecmp(&(t->prev_block_end_time),&time) > 0 ){
518 err=readBlock(t,t->which_block-1);
519 if(err) return err;
520 return ltt_tracefile_seek_time(t, time) ;
521 }else{
522 updateTracefile(t);
523 }
524 }
525 }else if(tailTime <= 0){
526 if(t->which_block != t->block_number){
527 err=readBlock(t,t->which_block+1);
528 if(err) return err;
529 }else return ENOENT;
530 if(tailTime < 0) return ltt_tracefile_seek_time(t, time);
531 }else if(headTime == 0){
532 updateTracefile(t);
533 }
534 return 0;
535 }
536
537 /*****************************************************************************
538 *Function name
539 * ltt_tracefile_read : read the next event
540 *Input params
541 * t : tracefile
542 *Return value
543 * ltt_event * : an event to be processed
544 ****************************************************************************/
545
546 ltt_event *ltt_tracefile_read(ltt_tracefile *t)
547 {
548 ltt_event * lttEvent = (ltt_event *)g_new(ltt_event, 1);
549 ltt_eventtype * evT;
550 ltt_facility * fac;
551
552 //update the fields of the current event and go to the next event
553 if(skipEvent(t)) return NULL;
554
555 t->current_event_time = getEventTime(t);
556
557 lttEvent->event_id = (int)(*(uint8_t *)(t->cur_event_pos));
558 evT = ltt_tracefile_eventtype_get(t, (unsigned)lttEvent->event_id);
559 fac = evT->facility;
560 if(evT->index == TRACE_EV_HEARTBEAT && strcmp(fac->name, "default")==0)
561 t->cur_heart_beat_number++;
562 lttEvent->cycle_count=*(uint32_t*)(t->cur_event_pos + EVENT_ID_SIZE);
563 lttEvent->tracefile = t;
564 lttEvent->data = t->cur_event_pos + EVENT_HEADER_SIZE;
565
566 return lttEvent;
567 }
568
569 /****************************************************************************
570 *Function name
571 * readFile : wrap function to read from a file
572 *Input Params
573 * fd : file descriptor
574 * buf : buf to contain the content
575 * size : number of bytes to be read
576 * mesg : message to be printed if some thing goes wrong
577 *return value
578 * 0 : success
579 * EIO : can not read from the file
580 ****************************************************************************/
581
582 int readFile(int fd, void * buf, size_t size, char * mesg)
583 {
584 ssize_t nbBytes;
585 nbBytes = read(fd, buf, size);
586 if(nbBytes != size){
587 printf("%s\n",mesg);
588 return EIO;
589 }
590 return 0;
591 }
592
593 /****************************************************************************
594 *Function name
595 * readBlock : read a block from the file
596 *Input Params
597 * lttdes : ltt trace file
598 * whichBlock : the block which will be read
599 *return value
600 * 0 : success
601 * EINVAL : lseek fail
602 * EIO : can not read from the file
603 ****************************************************************************/
604
605 int readBlock(ltt_tracefile * tf, int whichBlock)
606 {
607 off_t nbBytes;
608 uint32_t lostSize;
609
610 if(whichBlock - tf->which_block == 1 && tf->which_block != 0){
611 tf->prev_block_end_time = tf->a_block_footer->time;
612 }else{
613 tf->prev_block_end_time.tv_sec = 0;
614 tf->prev_block_end_time.tv_nsec = 0;
615 }
616 tf->prev_event_time.tv_sec = 0;
617 tf->prev_event_time.tv_nsec = 0;
618
619 nbBytes=lseek(tf->fd,(off_t)((whichBlock-1)*tf->trace_header->buffer_size),
620 SEEK_SET);
621 if(nbBytes == -1) return EINVAL;
622
623 if(readFile(tf->fd,tf->buffer,tf->trace_header->buffer_size,
624 "Unable to read a block")) return EIO;
625
626
627 tf->a_block_header=(block_header *) tf->buffer;
628 lostSize = *(uint32_t*)(tf->buffer + tf->trace_header->buffer_size
629 - sizeof(uint32_t));
630 /* skip event ID and time delta to get the address of the block foot */
631 tf->a_block_footer=(block_footer *)(tf->buffer+tf->trace_header->buffer_size
632 -lostSize+sizeof(uint8_t)+sizeof(uint32_t));
633 tf->which_block = whichBlock;
634 tf->which_event = 0;
635 tf->first_event_pos = tf->buffer + sizeof(block_header);
636 if(tf->which_block == 1){
637 tf->which_event++;
638 tf->first_event_pos += sizeof(trace_header_event);
639 }
640 tf->cur_event_pos = tf->first_event_pos;
641 tf->current_event_time = tf->a_block_header->time;
642 tf->cur_heart_beat_number = 0;
643
644 getCyclePerNsec(tf);
645
646 return 0;
647 }
648
649 /*****************************************************************************
650 *Function name
651 * updateTracefile : reinitialize the info of the block which is already
652 * in the buffer
653 *Input params
654 * tf : tracefile
655 ****************************************************************************/
656
657 void updateTracefile(ltt_tracefile * tf)
658 {
659 if(tf->which_block == 1)tf->which_event = 1;
660 else tf->which_event = 0;
661 tf->cur_event_pos = tf->first_event_pos;
662 tf->current_event_time = tf->a_block_header->time;
663 tf->cur_heart_beat_number = 0;
664
665 tf->prev_event_time.tv_sec = 0;
666 tf->prev_event_time.tv_nsec = 0;
667 }
668
669 /*****************************************************************************
670 *Function name
671 * skipEvent : go to the next event, update the fields of the current event
672 *Input params
673 * t : tracefile
674 *return value
675 * 0 : success
676 * EINVAL : lseek fail
677 * EIO : can not read from the file
678 * ENOENT : end of file
679 * ERANGE : event id is out of range
680 ****************************************************************************/
681
682 int skipEvent(ltt_tracefile * t)
683 {
684 int evId, err;
685 void * evData;
686 ltt_eventtype * evT;
687 ltt_field * rootFld;
688
689 evId = (int)(*(uint8_t *)(t->cur_event_pos));
690 evData = t->cur_event_pos + EVENT_HEADER_SIZE;
691 evT = ltt_tracefile_eventtype_get(t,(unsigned)evId);
692
693 if(evT) rootFld = evT->root_field;
694 else return ERANGE;
695
696 t->prev_event_time = getEventTime(t);
697
698 //event has string/sequence or the last event is not the same event
699 if((evT->latest_block!=t->which_block || evT->latest_event!=t->which_event)
700 && rootFld->field_fixed == 0){
701 setFieldsOffset(t, evT, evData);
702 }
703 t->cur_event_pos += EVENT_HEADER_SIZE + rootFld->field_size;
704
705 evT->latest_block = t->which_block;
706 evT->latest_event = t->which_event;
707
708 //the next event is in the next block
709 if(t->which_event == t->a_block_header->event_count - 1){
710 if(t->which_block == t->block_number) return ENOENT;
711 err = readBlock(t, t->which_block + 1);
712 if(err) return err;
713 }else{
714 t->which_event++;
715 }
716
717 return 0;
718 }
719
720 /*****************************************************************************
721 *Function name
722 * getCyclePerNsec : calculate cycles per nsec for current block
723 *Input Params
724 * t : tracefile
725 ****************************************************************************/
726
727 void getCyclePerNsec(ltt_tracefile * t)
728 {
729 ltt_time lBufTotalTime; /* Total time for this buffer */
730 ltt_cycle_count lBufTotalNSec; /* Total time for this buffer in nsecs */
731 ltt_cycle_count lBufTotalCycle;/* Total cycles for this buffer */
732
733 /* Calculate the total time for this buffer */
734 TimeSub(lBufTotalTime,t->a_block_footer->time, t->a_block_header->time);
735
736 /* Calculate the total cycles for this bufffer */
737 lBufTotalCycle = t->a_block_footer->cycle_count
738 - t->a_block_header->cycle_count;
739
740 /* Convert the total time to nsecs */
741 lBufTotalNSec = lBufTotalTime.tv_sec * 1000000000 + lBufTotalTime.tv_nsec;
742
743 t->cycle_per_nsec = (double)lBufTotalCycle / (double)lBufTotalNSec;
744 }
745
746 /****************************************************************************
747 *Function name
748 * getEventTime : obtain the time of an event
749 *Input params
750 * tf : tracefile
751 *Return value
752 * ltt_time : the time of the event
753 ****************************************************************************/
754
755 ltt_time getEventTime(ltt_tracefile * tf)
756 {
757 ltt_time time;
758 ltt_cycle_count cycle_count; /* cycle count for the current event */
759 ltt_cycle_count lEventTotalCycle; /* Total cycles from start for event */
760 double lEventNSec; /* Total usecs from start for event */
761 ltt_time lTimeOffset; /* Time offset in struct ltt_time */
762
763 /* Calculate total time in cycles from start of buffer for this event */
764 cycle_count = *(uint32_t*)(tf->cur_event_pos + EVENT_ID_SIZE);
765 if(tf->cur_heart_beat_number)
766 cycle_count += ((uint64_t)1)<<32 * tf->cur_heart_beat_number;
767 lEventTotalCycle=cycle_count-(tf->a_block_header->cycle_count & 0xFFFFFFFF);
768
769 /* Convert it to nsecs */
770 lEventNSec = lEventTotalCycle / tf->cycle_per_nsec;
771
772 /* Determine offset in struct ltt_time */
773 lTimeOffset.tv_nsec = (long)lEventNSec % 1000000000;
774 lTimeOffset.tv_sec = (long)lEventNSec / 1000000000;
775
776 TimeAdd(time, tf->a_block_header->time, lTimeOffset);
777
778 return time;
779 }
780
781 /*****************************************************************************
782 *Function name
783 * setFieldsOffset : set offset of the fields
784 *Input params
785 * tracefile : opened trace file
786 * evT : the event type
787 * evD : event data, it may be NULL
788 ****************************************************************************/
789
790 void setFieldsOffset(ltt_tracefile * t, ltt_eventtype * evT, void * evD)
791 {
792 ltt_field * rootFld = evT->root_field;
793 // rootFld->base_address = evD;
794
795 rootFld->field_size = getFieldtypeSize(t, evT, 0,0,rootFld, evD);
796 }
797
798 /*****************************************************************************
799 *Function name
800 * getFieldtypeSize: get the size of the field type (primitive type)
801 *Input params
802 * tracefile : opened trace file
803 * evT : event type
804 * offsetRoot : offset from the root
805 * offsetParent : offset from the parrent
806 * fld : field
807 * evD : event data, it may be NULL
808 *Return value
809 * int : size of the field
810 ****************************************************************************/
811
812 int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot,
813 int offsetParent, ltt_field * fld, void * evD)
814 {
815 int size, size1, element_number, i, offset1, offset2;
816 ltt_type * type = fld->field_type;
817
818 if(evT->latest_block==t->which_block && evT->latest_event==t->which_event){
819 return fld->field_size;
820 }
821
822 if(fld->field_fixed == 1){
823 if(fld == evT->root_field) return fld->field_size;
824 }
825
826 if(type->type_class != LTT_STRUCT && type->type_class != LTT_ARRAY &&
827 type->type_class != LTT_SEQUENCE && type->type_class != LTT_STRING){
828 if(fld->field_fixed == -1){
829 size = (int) ltt_type_size(t, type);
830 fld->field_fixed = 1;
831 }else size = fld->field_size;
832
833 }else if(type->type_class == LTT_ARRAY){
834 element_number = (int) type->element_number;
835 if(fld->field_fixed == -1){
836 size = getFieldtypeSize(t, evT, offsetRoot,0,fld->child[0], NULL);
837 if(size == 0){ //has string or sequence
838 fld->field_fixed = 0;
839 }else{
840 fld->field_fixed = 1;
841 size *= element_number;
842 }
843 }else if(fld->field_fixed == 0){// has string or sequence
844 size = 0;
845 for(i=0;i<element_number;i++){
846 size += getFieldtypeSize(t, evT, offsetRoot+size,size,
847 fld->child[0], evD+size);
848 }
849 }else size = fld->field_size;
850
851 }else if(type->type_class == LTT_SEQUENCE){
852 size1 = (int) ltt_type_size(t, type);
853 if(fld->field_fixed == -1){
854 fld->field_fixed = 0;
855 size = getFieldtypeSize(t, evT, offsetRoot,0,fld->child[0], NULL);
856 fld->element_size = size;
857 }else{//0: sequence
858 element_number = getIntNumber(size1,evD);
859 type->element_number = element_number;
860 if(fld->element_size > 0){
861 size = element_number * fld->element_size;
862 }else{//sequence has string or sequence
863 size = 0;
864 for(i=0;i<element_number;i++){
865 size += getFieldtypeSize(t, evT, offsetRoot+size+size1,size+size1,
866 fld->child[0], evD+size+size1);
867 }
868 }
869 size += size1;
870 }
871
872 }else if(type->type_class == LTT_STRING){
873 size = 0;
874 if(fld->field_fixed == -1){
875 fld->field_fixed = 0;
876 }else{//0: string
877 size = sizeof((char*)evD) + 1; //include end : '\0'
878 }
879
880 }else if(type->type_class == LTT_STRUCT){
881 element_number = (int) type->element_number;
882 size = 0;
883 if(fld->field_fixed == -1){
884 offset1 = offsetRoot;
885 offset2 = 0;
886 for(i=0;i<element_number;i++){
887 size1=getFieldtypeSize(t, evT,offset1,offset2, fld->child[i], NULL);
888 if(size1 > 0 && size >= 0){
889 size += size1;
890 if(offset1 >= 0) offset1 += size1;
891 offset2 += size1;
892 }else{
893 size = -1;
894 offset1 = -1;
895 offset2 = -1;
896 }
897 }
898 if(size == -1){
899 fld->field_fixed = 0;
900 size = 0;
901 }else fld->field_fixed = 1;
902 }else if(fld->field_fixed == 0){
903 offset1 = offsetRoot;
904 offset2 = 0;
905 for(i=0;i<element_number;i++){
906 size=getFieldtypeSize(t,evT,offset1,offset2,fld->child[i],evD+offset2);
907 offset1 += size;
908 offset2 += size;
909 }
910 size = offset2;
911 }else size = fld->field_size;
912 }
913
914 fld->offset_root = offsetRoot;
915 fld->offset_parent = offsetParent;
916 if(!evD){
917 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
918 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
919 }
920 fld->field_size = size;
921
922 return size;
923 }
924
925 /*****************************************************************************
926 *Function name
927 * timecmp : compare two time
928 *Input params
929 * t1 : first time
930 * t2 : second time
931 *Return value
932 * int : 0: t1 == t2; -1: t1 < t2; 1: t1 > t2
933 ****************************************************************************/
934
935 int timecmp(ltt_time * t1, ltt_time * t2)
936 {
937 ltt_time T;
938 TimeSub(T, *t1, *t2);
939 if(T.tv_sec == 0 && T.tv_nsec == 0) return 0;
940 else if(T.tv_sec > 0 || (T.tv_sec==0 && T.tv_nsec > 0)) return 1;
941 else return -1;
942 }
943
944 /*****************************************************************************
945 *Function name
946 * getIntNumber : get an integer number
947 *Input params
948 * size : the size of the integer
949 * evD : the event data
950 *Return value
951 * int : an integer
952 ****************************************************************************/
953
954 int getIntNumber(int size, void *evD)
955 {
956 int64_t i;
957 if(size == 1) i = *(int8_t *)evD;
958 else if(size == 2) i = *(int16_t *)evD;
959 else if(size == 4) i = *(int32_t *)evD;
960 else if(size == 8) i = *(int64_t *)evD;
961
962 return (int) i;
963 }
964
965 /*****************************************************************************
966 *Function name
967 * getDataEndianType : get the data type size and endian type of the local
968 * machine
969 *Input params
970 * size : size of data type
971 * endian : endian type, little or big
972 ****************************************************************************/
973
974 void getDataEndianType(ltt_arch_size * size, ltt_arch_endian * endian)
975 {
976 int i = 1;
977 char c = (char) i;
978 int sizeInt=sizeof(int), sizeLong=sizeof(long), sizePointer=sizeof(void *);
979
980 if(c == 1) *endian = LTT_LITTLE_ENDIAN;
981 else *endian = LTT_BIG_ENDIAN;
982
983 if(sizeInt == 2 && sizeLong == 4 && sizePointer == 4)
984 *size = LTT_LP32;
985 else if(sizeInt == 4 && sizeLong == 4 && sizePointer == 4)
986 *size = LTT_ILP32;
987 else if(sizeInt == 4 && sizeLong == 8 && sizePointer == 8)
988 *size = LTT_LP64;
989 else if(sizeInt == 8 && sizeLong == 8 && sizePointer == 8)
990 *size = LTT_ILP64;
991 else *size = LTT_UNKNOWN;
992 }
993
This page took 0.054836 seconds and 5 git commands to generate.