5 #include <linux/errno.h>
9 #include <ltt/tracefile.h>
11 #include "default.h" //yxx test
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
);
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
);
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
);
26 /* calculate cycles per nsec for current block */
27 void getCyclePerNsec(ltt_tracefile
* t
);
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
);
34 /* reinitialize the info of the block which is already in the buffer */
35 void updateTracefile(ltt_tracefile
* tf
);
37 /* go to the next event */
38 int skipEvent(ltt_tracefile
* t
);
40 /* compare two time (ltt_time), 0:t1=t2, -1:t1<t2, 1:t1>t2 */
41 int timecmp(ltt_time
* t1
, ltt_time
* t2
);
43 /* get an integer number */
44 int getIntNumber(int size1
, void *evD
);
47 /* Time operation macros for ltt_time (struct timespec) */
49 #define TimeSub(T3, T2, T1) \
52 (T3).tv_sec = (T2).tv_sec - (T1).tv_sec; \
53 (T3).tv_nsec = (T2).tv_nsec - (T1).tv_nsec; \
57 (T3).tv_nsec += 1000000000;\
62 #define TimeAdd(T3, T2, T1) \
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)\
69 (T3).tv_sec += (T3).tv_nsec / 1000000000;\
70 (T3).tv_nsec = (T3).tv_nsec % 1000000000;\
76 /*****************************************************************************
78 * ltt_tracefile_open : open a trace file, construct a ltt_tracefile
80 * pathname : path name of the trace file
82 * ltt_tracefile * : the structure represents the opened trace file
83 ****************************************************************************/
85 ltt_tracefile
*ltt_tracefile_open(char * fileName
)
88 struct stat lTDFStat
; /* Trace data file status */
89 trace_header_event
*trace_header
;
90 block_header a_block_header
;
92 tf
= g_new(ltt_tracefile
, 1);
95 tf
->fd
= open(fileName
, O_RDONLY
, 0);
97 g_error("Unable to open input data file %s\n", fileName
);
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
);
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
);
110 //store the size of the file
111 tf
->file_size
= lTDFStat
.st_size
;
113 //read the first block header
114 if(readFile(tf
->fd
,(void*)&a_block_header
, sizeof(block_header
),
115 "Unable to read block header"))
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"))
124 tf
->block_number
= tf
->file_size
/ trace_header
->buffer_size
;
125 tf
->trace_header
= (trace_header_event
*)trace_header
;
127 //allocate memory to contain the info of a block
128 tf
->buffer
= (void *) g_new(char, trace_header
->buffer_size
);
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
;
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
;
139 //get local machine's data type size and endian type
140 getDataEndianType(&(tf
->my_arch_size
), &(tf
->my_arch_endian
));
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();
153 /*****************************************************************************
155 * ltt_tracefile_close: close a trace file, release all facilities if their
156 * usage count == 0 when close_facilities is true
158 * t : tracefile which will be closed
159 * close_facilities : bool to show if the facilities need to be released
162 ****************************************************************************/
164 int ltt_tracefile_close(ltt_tracefile
*t
, int close_facilities
)
166 //free index_facility table
167 g_hash_table_foreach (t
->index_facility
, freeKey
, NULL
);
168 g_hash_table_destroy(t
->index_facility
);
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
);
174 //free eventtype_event_id array
175 g_ptr_array_free (t
->eventtype_event_id
, TRUE
);
177 //free facility_name table
178 g_hash_table_foreach (t
->facility_name
, freeFacilityNameTable
,
180 g_hash_table_destroy(t
->facility_name
);
182 //free tracefile structure
183 g_free(t
->trace_header
);
189 /*****************************************************************************
190 * functions to release the memory occupied by the tables of a tracefile
191 ****************************************************************************/
193 void freeKey (gpointer key
, gpointer value
, gpointer user_data
)
198 void freeValue (gpointer key
, gpointer value
, gpointer user_data
)
203 void freeFacilityNameTable (gpointer key
, gpointer value
, gpointer user_data
)
205 ltt_facility
* fac
= (ltt_facility
*) value
;
207 if(GPOINTER_TO_INT(user_data
) != 0)
208 ltt_facility_close(fac
);
211 /*****************************************************************************
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
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
224 ****************************************************************************/
226 int ltt_tracefile_facility_add(ltt_tracefile
*t
,ltt_facility
*f
,int base_id
)
233 //increase the facility usage count
235 t
->eventtype_number
+= f
->event_number
;
236 t
->facility_number
++;
238 //insert the facility into index_facility table
240 *id
= t
->facility_number
;
241 g_hash_table_insert(t
->index_facility
, (gpointer
)id
,(gpointer
)f
);
243 //insert facility name into table: base_id_name
246 g_hash_table_insert(t
->base_id_name
, (gpointer
)(f
->name
), (gpointer
)id
);
248 //insert facility name into table: facility_name
249 g_hash_table_insert(t
->facility_name
, (gpointer
)(f
->name
), (gpointer
)f
);
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
);
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
;
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
]);
276 for(i
=0; i
<f
->event_number
; i
++){
278 setFieldsOffset(t
, et
, NULL
);
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 ****************************************************************************/
295 uint32_t ltt_tracefile_arch_type(ltt_tracefile
*t
)
297 return t
->trace_header
->arch_type
;
300 uint32_t ltt_tracefile_arch_variant(ltt_tracefile
*t
)
302 return t
->trace_header
->arch_variant
;
305 ltt_arch_size
ltt_tracefile_arch_size(ltt_tracefile
*t
)
307 return t
->trace_header
->arch_size
;
310 ltt_arch_endian
ltt_tracefile_arch_endian(ltt_tracefile
*t
)
312 return t
->trace_header
->arch_endian
;
315 uint32_t ltt_tracefile_system_type(ltt_tracefile
*t
)
317 return t
->trace_header
->system_type
;
320 char *ltt_tracefile_system_name(ltt_tracefile
*t
)
322 return t
->trace_header
->system_name
;
325 /*****************************************************************************
327 * ltt_tracefile_cpu_number: get the number of the cpu
331 * unsigned : the number of cpu the system has
332 ****************************************************************************/
334 unsigned ltt_tracefile_cpu_number(ltt_tracefile
*t
)
336 return (unsigned)(t
->trace_header
->cpu_number
);
339 /*****************************************************************************
341 * ltt_tracefile_cpu_single: does the tracefile contain events only for a
346 * int : 1 for YES, 0 for NO
347 ****************************************************************************/
349 int ltt_tracefile_cpu_single(ltt_tracefile
*t
)
351 if(t
->trace_header
->cpu_number_used
== 1) return 1;
355 /*****************************************************************************
357 * ltt_tracefile_cpu_id: which CPU is contained in the tracefile?
362 ****************************************************************************/
364 unsigned ltt_tracefile_cpu_id(ltt_tracefile
*t
)
366 return (unsigned)(t
->trace_header
->cpu_id
);
369 /*****************************************************************************
370 * The following functions get the times related to the tracefile
371 ****************************************************************************/
373 ltt_time
ltt_tracefile_time_start(ltt_tracefile
*t
)
375 return t
->start_time
;
378 ltt_time
ltt_tracefile_time_end(ltt_tracefile
*t
)
383 ltt_time
ltt_tracefile_duration(ltt_tracefile
*t
)
386 TimeSub(T
, t
->end_time
, t
->start_time
);
390 /*****************************************************************************
391 * The following functions discover the facilities added to the tracefile
392 ****************************************************************************/
394 unsigned ltt_tracefile_facility_number(ltt_tracefile
*t
)
396 return (unsigned)(t
->facility_number
);
399 ltt_facility
*ltt_tracefile_facility_get(ltt_tracefile
*t
, unsigned i
)
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
);
406 ltt_facility
*ltt_tracefile_facility_get_by_name(ltt_tracefile
*t
,char *name
)
409 fac
=(ltt_facility
*)g_hash_table_lookup(t
->facility_name
,(gconstpointer
)name
);
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,
417 ****************************************************************************/
419 unsigned ltt_tracefile_eventtype_number(ltt_tracefile
*t
)
421 return t
->eventtype_number
;
424 ltt_eventtype
*ltt_tracefile_eventtype_get(ltt_tracefile
*t
, unsigned evId
)
427 ptr
= (ptr_wrap
*)g_ptr_array_index(t
->eventtype_event_id
, (gint
)evId
);
428 return (ltt_eventtype
*)(ptr
->ptr
);
431 /*****************************************************************************
433 * ltt_tracefile_eventtype_id
434 * : given an event type, find its unique id within
440 * unsigned : id of the event type in the tracefile
441 ****************************************************************************/
443 unsigned ltt_tracefile_eventtype_id(ltt_tracefile
*t
, ltt_eventtype
*et
)
446 char *name
= et
->facility
->name
;
448 id
= (int*)g_hash_table_lookup(t
->base_id_name
, (gconstpointer
)name
);
450 return (unsigned)(*id
+ et
->index
);
453 /*****************************************************************************
455 * ltt_tracefile_eventtype_root_field
456 * : get the root field associated with an event type
462 * ltt_field * : root field of the event
463 ****************************************************************************/
465 ltt_field
*ltt_tracefile_eventtype_root_field(ltt_tracefile
*t
, unsigned id
)
468 et
= ltt_tracefile_eventtype_get(t
, id
);
470 return et
->root_field
;
473 /*****************************************************************************
475 * ltt_tracefile_seek_time: seek to the first event of the trace with time
476 * larger or equal to time
479 * time : criteria of the time
482 * ENOENT, end of the file
484 * EIO, can not read from the file
485 ****************************************************************************/
487 int ltt_tracefile_seek_time(ltt_tracefile
*t
, ltt_time time
)
491 int headTime
= timecmp(&(t
->a_block_header
->time
), &time
);
492 int tailTime
= timecmp(&(t
->a_block_footer
->time
), &time
);
494 if(headTime
< 0 && tailTime
> 0){
495 lttTime
= getEventTime(t
);
496 err
= timecmp(<tTime
, &time
);
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 ) ){
503 return ltt_tracefile_seek_time(t
, time
);
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
);
511 }else if(headTime
> 0){
512 if(t
->which_block
== 1){
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);
520 return ltt_tracefile_seek_time(t
, time
) ;
525 }else if(tailTime
<= 0){
526 if(t
->which_block
!= t
->block_number
){
527 err
=readBlock(t
,t
->which_block
+1);
530 if(tailTime
< 0) return ltt_tracefile_seek_time(t
, time
);
531 }else if(headTime
== 0){
537 /*****************************************************************************
539 * ltt_tracefile_read : read the next event
543 * ltt_event * : an event to be processed
544 ****************************************************************************/
546 ltt_event
*ltt_tracefile_read(ltt_tracefile
*t
)
548 ltt_event
* lttEvent
= (ltt_event
*)g_new(ltt_event
, 1);
552 //update the fields of the current event and go to the next event
553 if(skipEvent(t
)) return NULL
;
555 t
->current_event_time
= getEventTime(t
);
557 lttEvent
->event_id
= (int)(*(uint8_t *)(t
->cur_event_pos
));
558 evT
= ltt_tracefile_eventtype_get(t
, (unsigned)lttEvent
->event_id
);
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
;
569 /****************************************************************************
571 * readFile : wrap function to read from a file
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
579 * EIO : can not read from the file
580 ****************************************************************************/
582 int readFile(int fd
, void * buf
, size_t size
, char * mesg
)
585 nbBytes
= read(fd
, buf
, size
);
593 /****************************************************************************
595 * readBlock : read a block from the file
597 * lttdes : ltt trace file
598 * whichBlock : the block which will be read
601 * EINVAL : lseek fail
602 * EIO : can not read from the file
603 ****************************************************************************/
605 int readBlock(ltt_tracefile
* tf
, int whichBlock
)
610 if(whichBlock
- tf
->which_block
== 1 && tf
->which_block
!= 0){
611 tf
->prev_block_end_time
= tf
->a_block_footer
->time
;
613 tf
->prev_block_end_time
.tv_sec
= 0;
614 tf
->prev_block_end_time
.tv_nsec
= 0;
616 tf
->prev_event_time
.tv_sec
= 0;
617 tf
->prev_event_time
.tv_nsec
= 0;
619 nbBytes
=lseek(tf
->fd
,(off_t
)((whichBlock
-1)*tf
->trace_header
->buffer_size
),
621 if(nbBytes
== -1) return EINVAL
;
623 if(readFile(tf
->fd
,tf
->buffer
,tf
->trace_header
->buffer_size
,
624 "Unable to read a block")) return EIO
;
627 tf
->a_block_header
=(block_header
*) tf
->buffer
;
628 lostSize
= *(uint32_t*)(tf
->buffer
+ tf
->trace_header
->buffer_size
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
;
635 tf
->first_event_pos
= tf
->buffer
+ sizeof(block_header
);
636 if(tf
->which_block
== 1){
638 tf
->first_event_pos
+= sizeof(trace_header_event
);
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;
649 /*****************************************************************************
651 * updateTracefile : reinitialize the info of the block which is already
655 ****************************************************************************/
657 void updateTracefile(ltt_tracefile
* tf
)
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;
665 tf
->prev_event_time
.tv_sec
= 0;
666 tf
->prev_event_time
.tv_nsec
= 0;
669 /*****************************************************************************
671 * skipEvent : go to the next event, update the fields of the current event
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 ****************************************************************************/
682 int skipEvent(ltt_tracefile
* t
)
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
);
693 if(evT
) rootFld
= evT
->root_field
;
696 t
->prev_event_time
= getEventTime(t
);
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
);
703 t
->cur_event_pos
+= EVENT_HEADER_SIZE
+ rootFld
->field_size
;
705 evT
->latest_block
= t
->which_block
;
706 evT
->latest_event
= t
->which_event
;
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);
720 /*****************************************************************************
722 * getCyclePerNsec : calculate cycles per nsec for current block
725 ****************************************************************************/
727 void getCyclePerNsec(ltt_tracefile
* t
)
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 */
733 /* Calculate the total time for this buffer */
734 TimeSub(lBufTotalTime
,t
->a_block_footer
->time
, t
->a_block_header
->time
);
736 /* Calculate the total cycles for this bufffer */
737 lBufTotalCycle
= t
->a_block_footer
->cycle_count
738 - t
->a_block_header
->cycle_count
;
740 /* Convert the total time to nsecs */
741 lBufTotalNSec
= lBufTotalTime
.tv_sec
* 1000000000 + lBufTotalTime
.tv_nsec
;
743 t
->cycle_per_nsec
= (double)lBufTotalCycle
/ (double)lBufTotalNSec
;
746 /****************************************************************************
748 * getEventTime : obtain the time of an event
752 * ltt_time : the time of the event
753 ****************************************************************************/
755 ltt_time
getEventTime(ltt_tracefile
* tf
)
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 */
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);
769 /* Convert it to nsecs */
770 lEventNSec
= lEventTotalCycle
/ tf
->cycle_per_nsec
;
772 /* Determine offset in struct ltt_time */
773 lTimeOffset
.tv_nsec
= (long)lEventNSec
% 1000000000;
774 lTimeOffset
.tv_sec
= (long)lEventNSec
/ 1000000000;
776 TimeAdd(time
, tf
->a_block_header
->time
, lTimeOffset
);
781 /*****************************************************************************
783 * setFieldsOffset : set offset of the fields
785 * tracefile : opened trace file
786 * evT : the event type
787 * evD : event data, it may be NULL
788 ****************************************************************************/
790 void setFieldsOffset(ltt_tracefile
* t
, ltt_eventtype
* evT
, void * evD
)
792 ltt_field
* rootFld
= evT
->root_field
;
793 // rootFld->base_address = evD;
795 rootFld
->field_size
= getFieldtypeSize(t
, evT
, 0,0,rootFld
, evD
);
798 /*****************************************************************************
800 * getFieldtypeSize: get the size of the field type (primitive type)
802 * tracefile : opened trace file
804 * offsetRoot : offset from the root
805 * offsetParent : offset from the parrent
807 * evD : event data, it may be NULL
809 * int : size of the field
810 ****************************************************************************/
812 int getFieldtypeSize(ltt_tracefile
* t
, ltt_eventtype
* evT
, int offsetRoot
,
813 int offsetParent
, ltt_field
* fld
, void * evD
)
815 int size
, size1
, element_number
, i
, offset1
, offset2
;
816 ltt_type
* type
= fld
->field_type
;
818 if(evT
->latest_block
==t
->which_block
&& evT
->latest_event
==t
->which_event
){
819 return fld
->field_size
;
822 if(fld
->field_fixed
== 1){
823 if(fld
== evT
->root_field
) return fld
->field_size
;
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
;
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;
840 fld
->field_fixed
= 1;
841 size
*= element_number
;
843 }else if(fld
->field_fixed
== 0){// has string or sequence
845 for(i
=0;i
<element_number
;i
++){
846 size
+= getFieldtypeSize(t
, evT
, offsetRoot
+size
,size
,
847 fld
->child
[0], evD
+size
);
849 }else size
= fld
->field_size
;
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
;
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
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
);
872 }else if(type
->type_class
== LTT_STRING
){
874 if(fld
->field_fixed
== -1){
875 fld
->field_fixed
= 0;
877 size
= sizeof((char*)evD
) + 1; //include end : '\0'
880 }else if(type
->type_class
== LTT_STRUCT
){
881 element_number
= (int) type
->element_number
;
883 if(fld
->field_fixed
== -1){
884 offset1
= offsetRoot
;
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){
890 if(offset1
>= 0) offset1
+= size1
;
899 fld
->field_fixed
= 0;
901 }else fld
->field_fixed
= 1;
902 }else if(fld
->field_fixed
== 0){
903 offset1
= offsetRoot
;
905 for(i
=0;i
<element_number
;i
++){
906 size
=getFieldtypeSize(t
,evT
,offset1
,offset2
,fld
->child
[i
],evD
+offset2
);
911 }else size
= fld
->field_size
;
914 fld
->offset_root
= offsetRoot
;
915 fld
->offset_parent
= offsetParent
;
917 fld
->fixed_root
= (offsetRoot
==-1) ? 0 : 1;
918 fld
->fixed_parent
= (offsetParent
==-1) ? 0 : 1;
920 fld
->field_size
= size
;
925 /*****************************************************************************
927 * timecmp : compare two time
932 * int : 0: t1 == t2; -1: t1 < t2; 1: t1 > t2
933 ****************************************************************************/
935 int timecmp(ltt_time
* t1
, ltt_time
* t2
)
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;
944 /*****************************************************************************
946 * getIntNumber : get an integer number
948 * size : the size of the integer
949 * evD : the event data
952 ****************************************************************************/
954 int getIntNumber(int size
, void *evD
)
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
;
965 /*****************************************************************************
967 * getDataEndianType : get the data type size and endian type of the local
970 * size : size of data type
971 * endian : endian type, little or big
972 ****************************************************************************/
974 void getDataEndianType(ltt_arch_size
* size
, ltt_arch_endian
* endian
)
978 int sizeInt
=sizeof(int), sizeLong
=sizeof(long), sizePointer
=sizeof(void *);
980 if(c
== 1) *endian
= LTT_LITTLE_ENDIAN
;
981 else *endian
= LTT_BIG_ENDIAN
;
983 if(sizeInt
== 2 && sizeLong
== 4 && sizePointer
== 4)
985 else if(sizeInt
== 4 && sizeLong
== 4 && sizePointer
== 4)
987 else if(sizeInt
== 4 && sizeLong
== 8 && sizePointer
== 8)
989 else if(sizeInt
== 8 && sizeLong
== 8 && sizePointer
== 8)
991 else *size
= LTT_UNKNOWN
;