9 #include <linux/errno.h>
11 //#include <sys/time.h>
22 int facilitiesNum
, totalNumEvents
;
23 kernel_facility
** idToFacility
; //corresponding between event id and kernel facility, it points to kFacilities
24 kernel_facility
** kFacilities
;
26 int intSize
[] = {sizeof(int8_t), sizeof(int16_t), sizeof(int32_t),
27 sizeof(int64_t), sizeof(short int), sizeof(int),
29 int uintSize
[] = {sizeof(uint8_t), sizeof(uint16_t), sizeof(uint32_t),
30 sizeof(uint64_t), sizeof(unsigned short int),
31 sizeof(unsigned int), sizeof(unsigned long) };
32 int floatSize
[] = {-1, -1, sizeof(float), sizeof(double),
33 -1, sizeof(float), sizeof(double)};
35 //will be deleted later, test
36 char *buf
[] = {"TRACE_EV_START", "TRACE_EV_SYSCALL_ENTRY", "TRACE_EV_SYSCALL_EXIT", "TRACE_EV_TRAP_ENTRY",
37 "TRACE_EV_TRAP_EXIT", "TRACE_EV_IRQ_ENTRY", "TRACE_EV_IRQ_EXIT", "TRACE_EV_SCHEDCHANGE",
38 "TRACE_EV_KERNEL_TIMER", "TRACE_EV_SOFT_IRQ", "TRACE_EV_PROCESS", "TRACE_EV_FILE_SYSTEM",
39 "TRACE_EV_TIMER", "TRACE_EV_MEMORY", "TRACE_EV_SOCKET", "TRACE_EV_IPC",
40 "TRACE_EV_NETWORK", "TRACE_EV_BUFFER_START", "TRACE_EV_BUFFER_END", "TRACE_EV_NEW_EVENT",
41 "TRACE_EV_CUSTOM", "TRACE_EV_CHANGE_MASK", "TRACE_EV_HEARTBEAT" };
43 void print_event( event_struct
* ev
){
45 sequence
* baseField
= ev
->base_field
;
47 field_handle
* fHandle
;
48 void* curPos
= ev
->data
;
52 fprintf(fp
,"Event id = %d, %s\n",ev
->event_id
, buf
[ev
->event_id
]);
54 for(i
=0;i
<baseField
->position
;i
++){
55 fHandle
= (field_handle
*) baseField
->array
[i
];
56 dt
= fHandle
->field_type
;
57 fprintf(fp
,"%s: ", fHandle
->name
);
58 if(dt
== INT
|| dt
== UINT
|| dt
== FLOAT
|| dt
== ENUM
){
60 if(fHandle
->size
== 4)fprintf(fp
, "%f\n",*(float*)(curPos
+fHandle
->offset
));
61 else fprintf(fp
, "%f\n",(float)(*(double*)(curPos
+fHandle
->offset
)));
63 if(fHandle
->size
== 1)fprintf(fp
, "%d\n",(int)(*(int8_t *)(curPos
+fHandle
->offset
)));
64 else if(fHandle
->size
== 2)fprintf(fp
, "%d\n",(int)(*(int16_t *)(curPos
+fHandle
->offset
)));
65 else if(fHandle
->size
== 4)fprintf(fp
, "%d\n",(int)(*(int32_t *)(curPos
+fHandle
->offset
)));
66 else if(fHandle
->size
== 8)fprintf(fp
, "%d\n",(int)(*(int64_t *)(curPos
+fHandle
->offset
)));
68 }else if(dt
== ARRAY
|| dt
== SEQUENCE
){
69 ch
= (char*)(curPos
+fHandle
->offset
);
70 offset
= curPos
+fHandle
->offset
;
71 for(j
=0;j
<fHandle
->nbElements
;j
++){
72 edt
= fHandle
->element_type
;
73 if(edt
== INT
|| edt
== UINT
|| edt
== FLOAT
|| edt
== ENUM
){
75 if(fHandle
->size
== 4)fprintf(fp
, "%f, ",*(float*)offset
);
76 else fprintf(fp
, "%f\n",(float)(*(double*)offset
));
78 if(fHandle
->size
== 1)fprintf(fp
, "%d, ",(int)(*(int8_t *)offset
));
79 else if(fHandle
->size
== 2)fprintf(fp
, "%d, ",(int)(*(int16_t *)offset
));
80 else if(fHandle
->size
== 4)fprintf(fp
, "%d, ",(int)(*(int32_t *)offset
));
81 else if(fHandle
->size
== 8)fprintf(fp
, "%d, ",(int)(*(int64_t *)offset
));
83 offset
+= fHandle
->size
;
84 }else if(edt
== STRING
){
85 fprintf(fp
,"%s, ", ch
);
87 if(*ch
== '\0'){ch
++; break;} //string ended with '\0'
90 }else if(edt
== ARRAY
|| edt
== SEQUENCE
|| edt
== STRUCT
){ // not supported
94 }else if(dt
== STRING
){
95 fprintf(fp
,"%s\n", (char*)(curPos
+fHandle
->offset
));
96 }else if (dt
== STRUCT
){ //not supported
105 /*****************************************************************************
107 * parseEventAndTypeDefinition: main function to parse event and type definition
108 ****************************************************************************/
109 void parseEventAndTypeDefinition(char * facilityName
){
112 char buffer
[BUFFER_SIZE
];
113 unsigned long checksum
;
117 sequence unnamedTypes
;
119 sequence_init(&events
);
120 table_init(&namedTypes
);
121 sequence_init(&unnamedTypes
);
125 in
.error
= error_callback
;
126 in
.name
= appendString(facilityName
,".event");
128 in
.fp
= fopen(in
.name
, "r");
129 if(!in
.fp
)in
.error(&in
,"cannot open input file");
132 token
= getToken(&in
);
133 if(in
.type
== ENDFILE
) break;
135 if(strcmp("event",token
) == 0) {
136 ev
= (event
*)memAlloc(sizeof(event
));
137 sequence_push(&events
,ev
);
138 parseEvent(&in
,ev
, &unnamedTypes
, &namedTypes
);
140 else if(strcmp("type",token
) == 0) {
141 parseTypeDefinition(&in
, &unnamedTypes
, &namedTypes
);
143 else in
.error(&in
,"event or type token expected");
148 checkNamedTypesImplemented(&namedTypes
);
150 generateChecksum(facilityName
, &checksum
, &events
);
152 generateFacilityHandle(facilityName
,checksum
,&events
);
157 sequence_dispose(&events
);
158 freeNamedType(&namedTypes
);
159 table_dispose(&namedTypes
);
160 freeTypes(&unnamedTypes
);
161 sequence_dispose(&unnamedTypes
);
165 /*****************************************************************************
167 * generateFacilityHandle : generate facility handle
169 * facName : facility name
170 * checksum : checksum of the facility
171 * events : sequence of events
172 ****************************************************************************/
173 void generateFacilityHandle(char * facName
, unsigned long checksum
, sequence
* events
){
174 int i
,j
, pos
,nbEvents
=0;
175 facility_handle
* facHandle
;
176 event_handle
* evHandle
;
177 field_handle
* fldHandle
;
183 //get number of events which do not have nested struct
184 for(i
=0;i
<events
->position
;i
++){
185 ev
= (event
*)events
->array
[i
];
186 if(ev
->nested
)continue;
190 //allocate memory for the facility
191 facHandle
= (facility_handle
*) memAlloc(sizeof(facility_handle
));
192 facHandle
->name
= allocAndCopy(facName
);
193 facHandle
->checksum
= checksum
;
194 facHandle
->nbEvents
= events
->position
;
195 facHandle
->events
= (event_handle
**)memAlloc(sizeof(event_handle
*) * nbEvents
);
197 //allocate memory for event handles and associate them with the facility
198 evHandle
= (event_handle
*)memAlloc(sizeof(event_handle
) * nbEvents
);
199 for(i
=0;i
<nbEvents
;i
++){
200 sequence_init(&evHandle
[i
].base_field
);
201 facHandle
->events
[i
] = &evHandle
[i
];
205 for(pos
=0;pos
<events
->position
;pos
++){
206 ev
= (event
*)events
->array
[pos
];
207 if(ev
->nested
)continue;
209 evHandle
[j
].name
= allocAndCopy(ev
->name
);
210 evHandle
[j
].id
= pos
;
211 evHandle
[j
].size_fixed
= 1; //by default there are no string or sequence
212 if(ev
->type
->fields
.position
){
213 fldHandle
= (field_handle
*)memAlloc(sizeof(field_handle
) * ev
->type
->fields
.position
);
215 evHandle
[j
].latest_block
= -1;
216 evHandle
[j
].latest_event
= -1;
217 offset
= EVENT_HEADER_SIZE(); //the beginning of the event is id and time delta
218 for(i
=0;i
<ev
->type
->fields
.position
;i
++){
219 fld
= (field
*)ev
->type
->fields
.array
[i
];
220 fldHandle
[i
].name
= allocAndCopy(fld
->name
);
221 fldHandle
[i
].field_type
= fld
->type
->type
;
222 dt
= fld
->type
->type
;
223 fldHandle
[i
].fmt
= NULL
;
224 fldHandle
[i
].element_type
= NONE
;
225 fldHandle
[i
].sequence_size
= -1;
226 fldHandle
[i
].offset
= -1;
227 fldHandle
[i
].end_field
= -1;
228 if(dt
==UINT
|| dt
==INT
|| dt
==FLOAT
|| dt
==ENUM
){
229 fldHandle
[i
].size
= getTypeSize(dt
, fld
->type
->size
);
230 if(evHandle
[j
].size_fixed
){
231 fldHandle
[i
].offset
= offset
;
232 offset
+= fldHandle
[i
].size
;
233 fldHandle
[i
].end_field
= offset
;
235 if(fld
->type
->fmt
) fldHandle
[i
].fmt
= allocAndCopy(fld
->type
->fmt
);
236 }else if(dt
==STRING
){
237 fldHandle
[i
].size
= -1; //-1 means: size is not known
238 if(evHandle
[j
].size_fixed
){
239 evHandle
[j
].size_fixed
= 0;
240 fldHandle
[i
].offset
= offset
;
243 if(fld
->type
->fmt
) fldHandle
[i
].fmt
= allocAndCopy(fld
->type
->fmt
);
244 }else if(dt
==ARRAY
|| dt
==SEQUENCE
){
245 fldHandle
[i
].size
= getTypeSize(fld
->type
->nested_type
->type
, fld
->type
->nested_type
->size
); //other primitive type
246 fldHandle
[i
].element_type
= fld
->type
->nested_type
->type
;
247 if(evHandle
[j
].size_fixed
){
248 fldHandle
[i
].offset
= offset
;
250 evHandle
[j
].size_fixed
= 0;
253 if(fldHandle
[i
].size
> 0){
254 offset
+= fld
->type
->size
* fldHandle
[i
].size
;
255 fldHandle
[i
].end_field
= offset
;
258 evHandle
[j
].size_fixed
= 0;
263 if(dt
==ARRAY
) fldHandle
[i
].nbElements
= fld
->type
->size
;
264 else fldHandle
[i
].nbElements
= -1; //is not known
265 if(dt
==SEQUENCE
) fldHandle
[i
].sequence_size
= getTypeSize(UINT
, fld
->type
->size
);
266 }else if(dt
==STRUCT
){
267 fldHandle
[i
].size
= -1; //impossible: do not support nested struct
268 if(evHandle
[j
].size_fixed
){
269 evHandle
[j
].size_fixed
= 0;
274 //add field handle into the sequence of field handles of the event handle
275 sequence_push(&evHandle
[j
].base_field
, &fldHandle
[i
]);
279 //add the facility handle into the sequence of facilities
280 sequence_push(&facilities
,facHandle
);
283 /*****************************************************************************
285 * getTypeSize : get the size of a given data type
288 * index : index of the data type
290 * int : return the size of the data type
291 ****************************************************************************/
292 int getTypeSize(data_type dt
, int index
){
296 size
= intSize
[index
];
300 size
= uintSize
[index
];
303 size
= floatSize
[index
];
314 /*****************************************************************************
316 * initFacilities: initialize the sequence for facilities and get all of the
317 * registered facilities from kernel
318 *****************************************************************************/
319 void initFacilities(){
322 sequence_init(&facilities
);
324 //get the number of the registered facilities from kernel
325 err
= getFacilitiesNumber( &facilitiesNum
, &totalNumEvents
);
327 printf("Unable to get the number of the registered facilities from kernel\n");
331 //get all of the registered facilities from kernel
332 kFacilities
= (kernel_facility
**)memAlloc(sizeof(kernel_facility
*) * facilitiesNum
);
333 for(i
=0;i
<facilitiesNum
;i
++){
334 kFacilities
[i
] = (kernel_facility
*)memAlloc(sizeof(kernel_facility
));
336 err
= getFacilitiesFromKernel(kFacilities
);
338 printf("Unable to get all of the registered facilities from kernel\n");
342 //set up the relation between event id and kernel facility
343 idToFacility
= (kernel_facility
**)memAlloc(sizeof(kernel_facility
*) * totalNumEvents
);
344 for(i
=0;i
<facilitiesNum
;i
++){
345 for(j
=kFacilities
[i
]->firstId
; j
< kFacilities
[i
]->firstId
+ kFacilities
[i
]->nbEvents
; j
++){
346 idToFacility
[j
] = kFacilities
[i
];
353 /*****************************************************************************
355 * trace_open_log : open trace files
357 * fileName : trace file name
359 * ltt_descriptor : handle to opened files
360 ****************************************************************************/
361 ltt_descriptor
* trace_open_log(char * fileName
){
362 ltt_descriptor
* lttdes
;
363 struct stat lTDFStat
; /* Trace data file status */
364 trace_header_event
*trace_header
;
365 block_header a_block_header
;
367 //initialize the sequence for facilities and get all registered facilities from kernel
370 lttdes
= (ltt_descriptor
*)memAlloc(sizeof(ltt_descriptor
));
373 lttdes
->fd
= open(fileName
, O_RDONLY
, 0);
375 printf("Unable to open input data file %s\n", fileName
);
379 // Get the file's status
380 if(fstat(lttdes
->fd
, &lTDFStat
) < 0){
381 printf("Unable to get the status of the input data file %s\n", fileName
);
385 // Is the file large enough to contain a trace
386 if(lTDFStat
.st_size
< sizeof(block_header
) + sizeof(trace_header_event
)){
387 printf("The input data file %s does not contain a trace\n", fileName
);
391 //store the size of the file
392 lttdes
->file_size
= lTDFStat
.st_size
;
394 //read the first block header
395 if(readFile(lttdes
->fd
,(void*)&a_block_header
, sizeof(block_header
), "Unable to read block header"))
398 //read the trace header event
399 trace_header
= memAlloc(sizeof(trace_header_event
));
400 if(readFile(lttdes
->fd
,(void*)trace_header
, sizeof(trace_header_event
),"Unable to read trace header event"))
403 lttdes
->nbBlocks
= lttdes
->file_size
/ trace_header
->buffer_size
;
404 lttdes
->trace_header
= (trace_header_event
*)trace_header
;
406 //read the first block
407 lttdes
->buffer
= memAlloc(trace_header
->buffer_size
);
408 lseek(lttdes
->fd
, 0,SEEK_SET
);
409 if(readBlock(lttdes
,1)) exit(1);
411 if(lttdes
->trace_header
->magic_number
== TRACER_MAGIC_NUMBER
) lttdes
->byte_rev
= 0;
412 else if(BREV32(lttdes
->trace_header
->magic_number
) == TRACER_MAGIC_NUMBER
) lttdes
->byte_rev
= 1;
420 /*****************************************************************************
422 * getFacilitiesNumber : get the number of the registered facilities
423 * and the total number of events from kernel
425 * facNum : point to the number of registered facilities
428 ****************************************************************************/
429 int getFacilitiesNumber(int * numFac
, int * numEvents
){
430 //not implemented yet
434 /*****************************************************************************
436 * getFacilitiesFromKernel : get all the registered facilities from kernel
438 * kFacilities : an array of kernel facility structure
441 ****************************************************************************/
442 int getFacilitiesFromKernel(kernel_facility
** kFacilities
){
443 //not implemented yet
448 /*****************************************************************************
450 * getTSCPerUsec : calculate cycles per Usec for current block
452 * lttdes : ltt file descriptor
453 ****************************************************************************/
454 void getTSCPerUsec(ltt_descriptor
* lttdes
){
455 struct timeval lBufTotalTime
; /* Total time for this buffer */
456 uint32_t lBufTotalUSec
; /* Total time for this buffer in usecs */
457 uint32_t lBufTotalTSC
; /* Total TSC cycles for this buffer */
459 /* Calculate the total time for this buffer */
460 DBTimeSub(lBufTotalTime
,lttdes
->a_block_footer
->time
, lttdes
->a_block_header
->time
);
461 /* Calculate the total cycles for this bufffer */
462 lBufTotalTSC
= lttdes
->a_block_footer
->tsc
- lttdes
->a_block_header
->tsc
;
463 /* Convert the total time to usecs */
464 lBufTotalUSec
= lBufTotalTime
.tv_sec
* 1000000 + lBufTotalTime
.tv_usec
;
466 lttdes
->TSCPerUsec
= (double)lBufTotalTSC
/ (double)lBufTotalUSec
;
469 /*****************************************************************************
471 * getEventTime : calculate the time the event occurs
473 * lttdes : ltt file descriptor
474 * time_delta : time difference between block header and the event
476 * pTime : pointer to event time
477 ****************************************************************************/
478 void getEventTime(ltt_descriptor
* lttdes
, uint32_t time_delta
, struct timeval
* pTime
){
479 uint32_t lEventTotalTSC
;/* Total cycles from start for event */
480 double lEventUSec
; /* Total usecs from start for event */
481 struct timeval lTimeOffset
; /* Time offset in struct timeval */
483 /* Calculate total time in TSCs from start of buffer for this event */
484 lEventTotalTSC
= time_delta
- lttdes
->a_block_header
->tsc
;
485 /* Convert it to usecs */
486 lEventUSec
= lEventTotalTSC
/lttdes
->TSCPerUsec
;
488 /* Determine offset in struct timeval */
489 lTimeOffset
.tv_usec
= (long)lEventUSec
% 1000000;
490 lTimeOffset
.tv_sec
= (long)lEventUSec
/ 1000000;
492 DBTimeAdd((*pTime
), lttdes
->a_block_header
->time
, lTimeOffset
);
496 /*****************************************************************************
498 * trace_read : get an event from the file
500 * lttdes : ltt file descriptor
501 * ev : a structure contains the event
504 * ENOENT : end of the file
505 * EIO : can not read from the file
506 * EINVAL : registered facility is not the same one used here
507 ****************************************************************************/
508 int trace_read(ltt_descriptor
* lttdes
, event_struct
* ev
){
511 facility_handle
* facHandle
;
513 event_handle
* eHandle
;
516 //check if it is the end of a block and if it is the end of the file
517 if(lttdes
->which_event
== lttdes
->a_block_header
->event_count
){
518 if(lttdes
->which_block
== lttdes
->nbBlocks
){
519 return ENOENT
; //end of file
521 if((err
=readBlock(lttdes
, lttdes
->which_block
+ 1)) != 0) return err
;
525 //get the event ID and time
526 evId
= *((int8_t*)lttdes
->cur_event_pos
);
527 time_delta
= *((uint32_t *)(lttdes
->cur_event_pos
+ EVENT_ID_SIZE()));
529 //get facility handle
530 err
= trace_lookup_facility(evId
, &facHandle
);
533 lttdes
->current_event_time
= time_delta
;
536 getEventTime(lttdes
, time_delta
, &(ev
->time
));
537 ev
->tsc
= time_delta
;
538 ev
->fHandle
= facHandle
;
540 // ev->event_id = evId - idToFacility[evId]->firstId; /* disable during the test */
543 ev
->ip_addr
= lttdes
->trace_header
->ip_addr
;
544 ev
->CPU_id
= lttdes
->trace_header
->cpuID
;
547 ev
->base_field
= &(ev
->fHandle
->events
[ev
->event_id
]->base_field
);
548 ev
->data
= lttdes
->cur_event_pos
;
550 //if there are strings or sequence in the event, update base field
551 eHandle
= ev
->fHandle
->events
[ev
->event_id
];
552 if(eHandle
->size_fixed
== 0 && (eHandle
->latest_block
!= lttdes
->which_block
|| eHandle
->latest_event
!= lttdes
->which_event
)){
553 if(ev
->base_field
->position
== 0) lttdes
->cur_event_pos
+= EVENT_HEADER_SIZE();
554 else trace_update_basefield(lttdes
, ev
->base_field
);
555 eHandle
->latest_block
= lttdes
->which_block
;
556 eHandle
->latest_event
= lttdes
->which_event
;
559 if(ev
->base_field
->position
== 0) lttdes
->cur_event_pos
+= EVENT_HEADER_SIZE();
561 //will be deleted late, test
562 tmp
= (int8_t *)lttdes
->cur_event_pos
;
563 for(err
=0;err
<((field_handle
*)ev
->base_field
->array
[ev
->base_field
->position
-1])->end_field
;err
++){
569 lttdes
->cur_event_pos
+= ((field_handle
*)ev
->base_field
->array
[ev
->base_field
->position
-1])->end_field
;
574 lttdes
->which_event
++;
576 //will be delete late, test
582 /*****************************************************************************
584 * trace_update_basefield : update base fields
586 * lttdes : ltt file descriptor
587 * baseField : base field of the event
588 ****************************************************************************/
589 void trace_update_basefield(ltt_descriptor
* lttdes
, sequence
* baseField
){
592 field_handle
* fHandle
;
594 off_t offset
= EVENT_HEADER_SIZE(); // id and time delta
596 int fixSize
= 1; //by default, no string or sequence
598 for(i
=0;i
<baseField
->position
;i
++){
599 fHandle
= (field_handle
*) baseField
->array
[i
];
600 dt
= fHandle
->field_type
;
601 curPos
= lttdes
->cur_event_pos
+ offset
;
602 if(dt
== INT
|| dt
== UINT
|| dt
== FLOAT
|| dt
== ENUM
){
603 if(!fixSize
) fHandle
->offset
= offset
;
604 offset
+= fHandle
->size
;
605 if(!fixSize
) fHandle
->end_field
= offset
;
606 }else if(dt
== ARRAY
|| dt
== SEQUENCE
){
607 edt
= fHandle
->element_type
;
610 if(fHandle
->sequence_size
== 1)fHandle
->nbElements
= (int)(*(uint8_t *)(curPos
));
611 else if(fHandle
->sequence_size
== 2)fHandle
->nbElements
= (int)(*(uint16_t *)(curPos
));
612 else if(fHandle
->sequence_size
== 3)fHandle
->nbElements
= (int)(*(uint32_t *)(curPos
));
613 else if(fHandle
->sequence_size
== 4)fHandle
->nbElements
= (int)(*(unsigned long *)(curPos
)); //
615 if(edt
== INT
|| edt
== UINT
|| edt
== FLOAT
|| edt
== ENUM
){
616 if(!fixSize
) fHandle
->offset
= offset
;
617 if(dt
== SEQUENCE
) offset
+= fHandle
->sequence_size
;
618 offset
+= fHandle
->nbElements
* fHandle
->size
;
619 if(!fixSize
) fHandle
->end_field
= offset
;
620 }else if(edt
== STRING
){
621 fHandle
->offset
= offset
;
623 curPos
+= fHandle
->sequence_size
;
624 offset
+= fHandle
->sequence_size
;
626 if(fixSize
) fixSize
= 0;
627 for(j
=0;j
<fHandle
->nbElements
;j
++){
629 ch
= *(char*)(curPos
);
632 if(ch
== '\0') break; //string ended with '\0'
635 fHandle
->end_field
= offset
;
636 }else if(edt
== ARRAY
|| edt
== SEQUENCE
|| edt
== STRUCT
){ // not supported
638 }else if(dt
== STRING
){
639 if(fixSize
) fixSize
= 0;
640 fHandle
->offset
= offset
;
642 ch
= *(char*)(curPos
);
645 if(ch
== '\0') break; //string ended with '\0'
647 fHandle
->end_field
= offset
;
648 }else if (dt
== STRUCT
){ //not supported
652 // lttdes->cur_event_pos = (void*)(&fHandle->end_field);
653 lttdes
->cur_event_pos
+= fHandle
->end_field
;
656 /****************************************************************************
658 * trace_lookup_facility: get the facility handle
660 * facilityName : facility name
662 * facHandle : facility handle
665 * EINVAL : registered facility is not the same one used here
666 ****************************************************************************/
667 int trace_lookup_facility(int evId
, facility_handle
** facHandle
){
669 facility_handle
* fHandle
;
671 for(i
=0;i
<facilities
.position
;i
++){
672 fHandle
= (facility_handle
*)facilities
.array
[i
];
674 /* disable during the test */
675 *facHandle
= fHandle
;
678 if(strcmp(idToFacility[evId]->name, fHandle->name)==0){
679 if(idToFacility[evId]->checksum != fHandle->checksum)
681 *facHandle = fHandle;
687 //read event definition file
688 // parseEventAndTypeDefinition(idToFacility[evId]->name); / * disable during the test */
689 parseEventAndTypeDefinition("default");
690 fHandle
= (facility_handle
*)facilities
.array
[facilities
.position
-1];
692 //check if the facility used here is the same as the one registered in kernel
693 // if(idToFacility[evId]->checksum != fHandle->checksum) return EINVAL; /* disable during the test */
695 *facHandle
= fHandle
;
700 /****************************************************************************
702 * trace_lookup_event: get the event handle
704 * event_id : id of event in the facility
705 * facHandle : facility handle containing an array of event handle
707 * eventHandle : event handle
710 ****************************************************************************/
711 int trace_lookup_event(int event_id
, facility_handle
* facHandle
, event_handle
** eventHandle
){
712 *eventHandle
= facHandle
->events
[event_id
];
716 /****************************************************************************
718 * trace_lookup_field: get field handle
720 * baseField : a sequence of field handles
721 * position : the position of the field handle in the baseField
723 * fieldHandle : field handle
726 * EINVAL : not a valid position
727 ****************************************************************************/
728 int trace_lookup_field(sequence
* baseField
, int position
, field_handle
** fieldHandle
){
729 if(position
>= baseField
->position
|| position
< 0) return EINVAL
;
730 *fieldHandle
= (field_handle
*)baseField
->array
[position
];
734 /****************************************************************************
736 * readFile : wrap function to read from a file
738 * fd : file descriptor
739 * buf : buf to contain the content
740 * size : number of bytes to be read
741 * mesg : message to be printed if some thing goes wrong
744 * EIO : can not read from the file
745 ****************************************************************************/
746 int readFile(int fd
, void * buf
, size_t size
, char * mesg
){
748 nbBytes
= read(fd
, buf
, size
);
756 /****************************************************************************
758 * trace_seek : seek according to event
760 * lttdes : ltt file descriptor
761 * offset : the file offset : event
762 * whence : how to set offset, it can be SEEK_SET, SEEK_CUR, SEEK_END
765 * EINVAL : lseek fail
766 * EIO : can not read from the file
767 * ENOENT : end of file
768 ****************************************************************************/
769 int trace_seek(ltt_descriptor
* lttdes
, off_t offset
, int whence
){
770 off_t newOffset
= offset
;
771 int blockNum
, i
,j
, err
;
774 if(whence
== SEEK_CUR
&& offset
== 0)return 0;
776 if(whence
== SEEK_SET
){
777 if(offset
< 0) return EINVAL
;
778 if(lttdes
->which_block
!= 1){
779 if((err
=readBlock(lttdes
, 1)) != 0) return err
;
780 }else updateLttdes(lttdes
);
781 }else if(whence
== SEEK_END
){
782 if(offset
> 0) return EINVAL
;
783 if(lttdes
->which_block
!= lttdes
->nbBlocks
){
784 if((err
=readBlock(lttdes
, lttdes
->nbBlocks
))!=0) return err
;
785 }else updateLttdes(lttdes
);
786 newOffset
= lttdes
->a_block_header
->event_count
+ offset
;
787 if(newOffset
> (off_t
)lttdes
->a_block_header
->event_count
) return EINVAL
;
788 }else{ //whence == SEEK_CUR
790 newOffset
= lttdes
->which_event
+ offset
;
791 updateLttdes(lttdes
);
792 if(lttdes
->which_block
== 1){
794 if(newOffset
< 0) return 0; //at the beginning of the file
799 //seek the right position of the event
801 while(newOffset
> (off_t
)(lttdes
->a_block_header
->event_count
- lttdes
->which_event
)){
802 if(lttdes
->which_block
== lttdes
->nbBlocks
) return ENOENT
; //end of file
803 newOffset
+= - lttdes
->a_block_header
->event_count
+ lttdes
->which_event
;
804 if((err
=readBlock(lttdes
, lttdes
->which_block
+1))!=0) return err
;
806 }else if(newOffset
< 0){
807 while(newOffset
<= 0){
808 if(lttdes
->which_block
== 1) return 0; //reach the beginning of the file
809 if((err
=readBlock(lttdes
, lttdes
->which_block
-1))!=0)return err
;
810 newOffset
+= lttdes
->a_block_header
->event_count
;
811 if(lttdes
->which_block
== 1) newOffset
--;
815 j
= lttdes
->which_event
;
816 for(i
=j
;i
<j
+newOffset
;i
++){
817 err
= trace_read(lttdes
,&ev
);
821 lttdes
->which_event
= i
;
822 if(lttdes
->which_event
== 0 || (lttdes
->which_event
== 1 && lttdes
->which_block
== 1))
823 lttdes
->current_event_time
= lttdes
->a_block_header
->tsc
;
824 else lttdes
->current_event_time
= ev
.tsc
;
829 /****************************************************************************
831 * readBlock : read a block from the file
833 * lttdes : ltt file descriptor
834 * whichBlock : the block which will be read
837 * EINVAL : lseek fail
838 * EIO : can not read from the file
839 ****************************************************************************/
840 int readBlock(ltt_descriptor
* lttdes
, int whichBlock
){
842 nbBytes
= lseek(lttdes
->fd
, (off_t
)((whichBlock
-1)*lttdes
->trace_header
->buffer_size
),SEEK_SET
);
843 if(nbBytes
== -1) return EINVAL
;
845 if(readFile(lttdes
->fd
,lttdes
->buffer
,lttdes
->trace_header
->buffer_size
,"Unable to read a block")) return EIO
;
846 lttdes
->a_block_header
= (block_header
*) lttdes
->buffer
;
847 lttdes
->a_block_footer
= (block_footer
*)(lttdes
->buffer
+ lttdes
->trace_header
->buffer_size
- sizeof(block_footer
));
848 lttdes
->which_block
= whichBlock
;
849 lttdes
->which_event
= 0;
850 lttdes
->first_event_pos
= lttdes
->buffer
+ sizeof(block_header
);
851 if(lttdes
->which_block
== 1){
852 lttdes
->which_event
++;
853 lttdes
->first_event_pos
+= sizeof(trace_header_event
);
855 lttdes
->cur_event_pos
= lttdes
->first_event_pos
;
856 lttdes
->current_event_time
= lttdes
->a_block_header
->tsc
;
858 getTSCPerUsec(lttdes
);
863 /****************************************************************************
865 * updateLttdes : update the info of ltt descriptor
867 * lttdes : ltt file descriptor
868 ****************************************************************************/
869 void updateLttdes(ltt_descriptor
* lttdes
){
870 if(lttdes
->which_block
== 1)lttdes
->which_event
= 1;
871 else lttdes
->which_event
= 0;
872 lttdes
->cur_event_pos
= lttdes
->first_event_pos
;
873 lttdes
->current_event_time
= lttdes
->a_block_header
->tsc
;
876 /****************************************************************************
878 * trace_seek_time : seek according to time
880 * lttdes : ltt file descriptor
881 * offset : the file offset : time
882 * whence : how to set offset, it can be SEEK_SET, SEEK_CUR, SEEK_END
885 * EINVAL : lseek fail
886 * EIO : can not read from the file
887 * ENOENT : end of file
888 ****************************************************************************/
889 int trace_seek_time(ltt_descriptor
* lttdes
, uint32_t offset
, int whence
){
890 uint32_t curTime
, seekTime
;
891 int blockNum
, i
,j
, err
;
895 uint32_t curEventTime
;
897 if(whence
== SEEK_CUR
&& offset
== 0)return 0;
899 if(whence
== SEEK_SET
){
900 if(offset
< 0) return EINVAL
;
901 if(lttdes
->which_block
!= 1){
902 if((err
=readBlock(lttdes
, 1))!=0) return err
;
903 }else updateLttdes(lttdes
);
904 curTime
= lttdes
->a_block_header
->tsc
;
905 }else if(whence
== SEEK_END
){
906 if(offset
> 0) return EINVAL
;
907 if(lttdes
->which_block
!= lttdes
->nbBlocks
){
908 if((err
=readBlock(lttdes
, lttdes
->nbBlocks
))!=0) return err
;
909 }else updateLttdes(lttdes
);
910 curTime
= lttdes
->a_block_footer
->tsc
;
912 curTime
= lttdes
->current_event_time
;
915 seekTime
= curTime
+ offset
;
917 //find the block which contains the time
919 if(whence
== SEEK_SET
)
920 blockNum
= -trace_get_time_block_position(lttdes
, seekTime
, 1, lttdes
->nbBlocks
);
921 else if(whence
== SEEK_CUR
)
922 blockNum
= -trace_get_time_block_position(lttdes
, seekTime
, lttdes
->which_block
, lttdes
->nbBlocks
);
924 if(whence
== SEEK_END
)
925 blockNum
= -trace_get_time_block_position(lttdes
, seekTime
, 1, lttdes
->nbBlocks
);
926 else if(whence
== SEEK_CUR
)
927 blockNum
= -trace_get_time_block_position(lttdes
, seekTime
, 1, lttdes
->which_block
);
929 if(whence
== SEEK_SET
) blockNum
= 1;
930 if(whence
== SEEK_END
) blockNum
= lttdes
->nbBlocks
;
933 if(blockNum
< 0) return -blockNum
;
936 if(lttdes
->which_block
!= blockNum
){
937 if((err
=readBlock(lttdes
,blockNum
))!=0) return err
;
938 }else updateLttdes(lttdes
);
940 if(lttdes
->a_block_footer
->tsc
<= seekTime
){
941 if(blockNum
== lttdes
->nbBlocks
) return ENOENT
; // end of file
945 //find the event whose time is just before the time
946 if(lttdes
->which_block
!= blockNum
){
947 if((err
=readBlock(lttdes
,blockNum
))!=0) return err
;
950 if(lttdes
->current_event_time
>= seekTime
) return 0; //find the right place
952 //loop through the block to find the event
953 j
= lttdes
->which_event
;
954 for(i
=j
;i
<lttdes
->a_block_header
->event_count
;i
++){
955 tmpAddr
= lttdes
->cur_event_pos
;
956 curEventTime
= lttdes
->current_event_time
;
957 whichEvent
= lttdes
->which_event
;
958 if((err
= trace_read(lttdes
,&ev
))!=0) return err
;
959 if(ev
.tsc
>= seekTime
){
960 lttdes
->cur_event_pos
= tmpAddr
;
961 lttdes
->current_event_time
= curEventTime
;
962 lttdes
->which_event
= whichEvent
;
967 //if we reach here that means this block does not contain the time, go to the next block;
968 if(blockNum
== lttdes
->nbBlocks
) return ENOENT
; // end of file
969 if((err
=readBlock(lttdes
,blockNum
+1))!=0) return err
;
974 /****************************************************************************
976 * trace_get_time_block_position : get the position of the block which
977 * contains the seekTime
979 * lttdes : ltt file descriptor
980 * seekTime : absolute time
981 * beginBlock : the start block from which to begin the search
982 * endBlock : the end block where to end the search
984 * negative number : the block number
985 * EINVAL : lseek fail
986 * EIO : can not read from the file
987 * ENOENT : end of file
988 ****************************************************************************/
989 int trace_get_time_block_position(ltt_descriptor
* lttdes
, uint32_t seekTime
, int beginBlock
, int endBlock
){
990 int err
, middleBlock
= (endBlock
+ beginBlock
) / 2;
992 if(beginBlock
== endBlock
)return -beginBlock
;
994 //get the start time of the block
995 if(lttdes
->which_block
!= middleBlock
){
996 if((err
=readBlock(lttdes
,middleBlock
))!=0) return err
;
998 updateLttdes(lttdes
);
1001 if(lttdes
->a_block_header
->tsc
>= seekTime
){
1002 if(middleBlock
-beginBlock
<= 1) return -beginBlock
;
1003 return trace_get_time_block_position(lttdes
, seekTime
,beginBlock
, middleBlock
-1);
1006 if(lttdes
->a_block_footer
->tsc
>= seekTime
) return -middleBlock
;
1007 if(endBlock
-middleBlock
== 1) return -endBlock
;
1008 return trace_get_time_block_position(lttdes
, seekTime
, middleBlock
+1, endBlock
);
1011 /****************************************************************************
1013 * trace_get_char, trace_get_uchar, trace_get_enum, trace_get_short
1014 * trace_get_ushort, trace_get_integer, trace_get_uinteger, trace_get_long
1015 * trace_get_ulong, trace_get_float, trace_get_double, trace_get_string
1016 * the help functions are used to get data of special data type from event
1019 * field : field handle
1020 * data : event binary data
1022 * corresponding data type
1023 ****************************************************************************/
1024 int trace_get_char(field_handle
* field
, void * data
){
1025 return (int)(*(char*)(data
+ field
->offset
));
1028 int trace_get_uchar(field_handle
* field
, void * data
){
1029 return (int)(*(unsigned char*)(data
+ field
->offset
));
1032 unsigned long trace_get_enum(field_handle
* field
, void * data
){
1033 if(field
->size
== 1)return (unsigned long)(*(uint8_t *)(data
+ field
->offset
));
1034 else if(field
->size
== 2)return (unsigned long)(*(uint16_t *)(data
+ field
->offset
));
1035 else if(field
->size
== 3)return (unsigned long)(*(uint32_t *)(data
+ field
->offset
));
1036 else if(field
->size
== 4)return *(unsigned long *)(data
+ field
->offset
);
1039 short int trace_get_short(field_handle
* field
, void * data
){
1040 return *(short int*)(data
+ field
->offset
);
1043 unsigned short int trace_get_ushort(field_handle
* field
, void * data
){
1044 return *(unsigned short int*)(data
+ field
->offset
);
1047 int trace_get_integer(field_handle
* field
, void * data
){
1048 return *(int*)(data
+ field
->offset
);
1051 unsigned int trace_get_uinteger(field_handle
* field
, void * data
){
1052 return *(unsigned int*)(data
+ field
->offset
);
1055 long trace_get_long(field_handle
* field
, void * data
){
1056 return *(long*)(data
+ field
->offset
);
1059 unsigned long trace_get_ulong(field_handle
* field
, void * data
){
1060 return *(unsigned long*)(data
+ field
->offset
);
1063 float trace_get_float(field_handle
* field
, void * data
){
1064 return *(float*)(data
+ field
->offset
);
1067 double trace_get_double(field_handle
* field
, void * data
){
1068 return *(double*)(data
+ field
->offset
);
1071 char * trace_get_string(field_handle
* field
, void * data
){
1072 return allocAndCopy((char*)(data
+ field
->offset
));
1076 //main and the following functions are just for the purpose of test, it will be deleted late
1078 int main(char * argc
, char ** argv
){
1080 facility_handle
* fH
;
1085 block_footer bf
, *ptr
;
1086 trace_header_event thev
;
1087 ltt_descriptor
* lttdes
;
1089 char buf
[BUFFER_SIZE
];
1091 fp
= fopen("statistic","w");
1093 printf("can not open test file\n");
1097 lttdes
= trace_open_log(argv
[1]);
1098 err
= trace_seek(lttdes
, 1, SEEK_SET
);
1099 for(i
=0;i
<lttdes
->a_block_header
->event_count
- 2;i
++){
1100 err
= trace_seek(lttdes
, 1, SEEK_CUR
);
1102 ptr
= (block_footer
*)(lttdes
->buffer
+ lttdes
->trace_header
->buffer_size
- sizeof(block_footer
));
1105 err = trace_seek_time(lttdes, 11, SEEK_SET);
1106 err = trace_seek_time(lttdes, 1060000000, SEEK_CUR);
1108 err = trace_seek_time(lttdes, 100000000, SEEK_CUR);