The code to print events is now part of textDump.c. If part of it is useful
[lttv.git] / ltt / branches / poly / misc / EventAPI.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <stdarg.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <sys/stat.h>
8 #include <sys/types.h>
9 #include <linux/errno.h>
10
11 //#include <sys/time.h>
12
13 #include "LTTTypes.h"
14
15 #include "parser.h"
16 #include "EventAPI.h"
17
18 //during the test
19 #include "default.h"
20
21 sequence facilities;
22 int facilitiesNum, totalNumEvents;
23 kernel_facility ** idToFacility; //corresponding between event id and kernel facility, it points to kFacilities
24 kernel_facility ** kFacilities;
25
26 int intSize[] = {sizeof(int8_t), sizeof(int16_t), sizeof(int32_t),
27 sizeof(int64_t), sizeof(short int), sizeof(int),
28 sizeof(long) };
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)};
34
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" };
42 FILE * fp;
43 void print_event( event_struct * ev){
44 int i,j;
45 sequence * baseField = ev->base_field;
46 char* ch;
47 field_handle * fHandle;
48 void* curPos = ev->data;
49 void * offset;
50 data_type dt, edt;
51
52 fprintf(fp,"Event id = %d, %s\n",ev->event_id, buf[ev->event_id]);
53
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){
59 if(dt == FLOAT){
60 if(fHandle->size == 4)fprintf(fp, "%f\n",*(float*)(curPos+fHandle->offset));
61 else fprintf(fp, "%f\n",(float)(*(double*)(curPos+fHandle->offset)));
62 }else{
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)));
67 }
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){
74 if(edt == FLOAT){
75 if(fHandle->size == 4)fprintf(fp, "%f, ",*(float*)offset);
76 else fprintf(fp, "%f\n",(float)(*(double*)offset));
77 }else{
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));
82 }
83 offset += fHandle->size;
84 }else if(edt == STRING){
85 fprintf(fp,"%s, ", ch);
86 while(1){
87 if(*ch == '\0'){ch++; break;} //string ended with '\0'
88 ch++;
89 }
90 }else if(edt == ARRAY || edt == SEQUENCE || edt == STRUCT){ // not supported
91 }
92 }
93 fprintf(fp,"\n");
94 }else if(dt == STRING){
95 fprintf(fp,"%s\n", (char*)(curPos+fHandle->offset));
96 }else if (dt == STRUCT){ //not supported
97 }
98 }
99
100 fprintf(fp,"\n\n");
101 // fflush(fp);
102 }
103 //end
104
105 /*****************************************************************************
106 *Function name
107 * parseEventAndTypeDefinition: main function to parse event and type definition
108 ****************************************************************************/
109 void parseEventAndTypeDefinition(char * facilityName){
110 char *token;
111 parse_file in;
112 char buffer[BUFFER_SIZE];
113 unsigned long checksum;
114 event *ev;
115 sequence events;
116 table namedTypes;
117 sequence unnamedTypes;
118
119 sequence_init(&events);
120 table_init(&namedTypes);
121 sequence_init(&unnamedTypes);
122
123 in.buffer = buffer;
124 in.lineno = 0;
125 in.error = error_callback;
126 in.name = appendString(facilityName,".event");
127
128 in.fp = fopen(in.name, "r");
129 if(!in.fp )in.error(&in,"cannot open input file");
130
131 while(1){
132 token = getToken(&in);
133 if(in.type == ENDFILE) break;
134
135 if(strcmp("event",token) == 0) {
136 ev = (event *)memAlloc(sizeof(event));
137 sequence_push(&events,ev);
138 parseEvent(&in,ev, &unnamedTypes, &namedTypes);
139 }
140 else if(strcmp("type",token) == 0) {
141 parseTypeDefinition(&in, &unnamedTypes, &namedTypes);
142 }
143 else in.error(&in,"event or type token expected");
144 }
145
146 fclose(in.fp);
147
148 checkNamedTypesImplemented(&namedTypes);
149
150 generateChecksum(facilityName, &checksum, &events);
151
152 generateFacilityHandle(facilityName,checksum,&events);
153
154
155 free(in.name);
156 freeEvents(&events);
157 sequence_dispose(&events);
158 freeNamedType(&namedTypes);
159 table_dispose(&namedTypes);
160 freeTypes(&unnamedTypes);
161 sequence_dispose(&unnamedTypes);
162
163 }
164
165 /*****************************************************************************
166 *Function name
167 * generateFacilityHandle : generate facility handle
168 *Input params
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;
178 event * ev;
179 field *fld;
180 data_type dt;
181 off_t offset;
182
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;
187 nbEvents++;
188 }
189
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);
196
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];
202 }
203
204 j = -1;
205 for(pos=0;pos<events->position;pos++){
206 ev = (event *)events->array[pos];
207 if(ev->nested)continue;
208 j++;
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);
214 }
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;
234 }
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;
241 offset = -1;
242 }
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;
249 if(dt==SEQUENCE){
250 evHandle[j].size_fixed = 0;
251 offset = -1;
252 }else{
253 if(fldHandle[i].size > 0){
254 offset += fld->type->size * fldHandle[i].size;
255 fldHandle[i].end_field = offset;
256 }
257 else{
258 evHandle[j].size_fixed = 0;
259 offset = -1;
260 }
261 }
262 }
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;
270 offset = -1;
271 }
272 }
273
274 //add field handle into the sequence of field handles of the event handle
275 sequence_push(&evHandle[j].base_field, &fldHandle[i]);
276 }
277 }
278
279 //add the facility handle into the sequence of facilities
280 sequence_push(&facilities,facHandle);
281 }
282
283 /*****************************************************************************
284 *Function name
285 * getTypeSize : get the size of a given data type
286 *Input params
287 * dt : data type
288 * index : index of the data type
289 *Output params
290 * int : return the size of the data type
291 ****************************************************************************/
292 int getTypeSize(data_type dt, int index){
293 int size = -1;
294 switch(dt){
295 case INT:
296 size = intSize[index];
297 break;
298 case UINT:
299 case ENUM:
300 size = uintSize[index];
301 break;
302 case FLOAT:
303 size = floatSize[index];
304 break;
305 case STRING:
306 case ARRAY:
307 case SEQUENCE:
308 case STRUCT:
309 default:
310 }
311 return size;
312 }
313
314 /*****************************************************************************
315 *Function name
316 * initFacilities: initialize the sequence for facilities and get all of the
317 * registered facilities from kernel
318 *****************************************************************************/
319 void initFacilities(){
320 int err, i, j;
321
322 sequence_init(&facilities);
323
324 //get the number of the registered facilities from kernel
325 err = getFacilitiesNumber( &facilitiesNum, &totalNumEvents);
326 if(err){
327 printf("Unable to get the number of the registered facilities from kernel\n");
328 exit(1);
329 }
330
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));
335 }
336 err = getFacilitiesFromKernel(kFacilities);
337 if(err){
338 printf("Unable to get all of the registered facilities from kernel\n");
339 exit(1);
340 }
341
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];
347 }
348 }
349
350 }
351
352
353 /*****************************************************************************
354 *Function name
355 * trace_open_log : open trace files
356 *Input Params
357 * fileName : trace file name
358 *Output Params
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;
366
367 //initialize the sequence for facilities and get all registered facilities from kernel
368 initFacilities();
369
370 lttdes = (ltt_descriptor *)memAlloc(sizeof(ltt_descriptor));
371
372 //open the file
373 lttdes->fd = open(fileName, O_RDONLY, 0);
374 if(lttdes->fd < 0){
375 printf("Unable to open input data file %s\n", fileName);
376 exit(1);
377 }
378
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);
382 exit(1);
383 }
384
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);
388 exit(1);
389 }
390
391 //store the size of the file
392 lttdes->file_size = lTDFStat.st_size;
393
394 //read the first block header
395 if(readFile(lttdes->fd,(void*)&a_block_header, sizeof(block_header), "Unable to read block header"))
396 exit(1);
397
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"))
401 exit(1);
402
403 lttdes->nbBlocks = lttdes->file_size / trace_header->buffer_size;
404 lttdes->trace_header = (trace_header_event *)trace_header;
405
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);
410
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;
413 else exit(1);
414
415
416
417 return lttdes;
418 }
419
420 /*****************************************************************************
421 *Function name
422 * getFacilitiesNumber : get the number of the registered facilities
423 * and the total number of events from kernel
424 *Input Params
425 * facNum : point to the number of registered facilities
426 *return value
427 * 0 : success
428 ****************************************************************************/
429 int getFacilitiesNumber(int * numFac, int * numEvents){
430 //not implemented yet
431 return 0;
432 }
433
434 /*****************************************************************************
435 *Function name
436 * getFacilitiesFromKernel : get all the registered facilities from kernel
437 *Input Params
438 * kFacilities : an array of kernel facility structure
439 *return value
440 * 0 : success
441 ****************************************************************************/
442 int getFacilitiesFromKernel(kernel_facility ** kFacilities){
443 //not implemented yet
444
445 return 0;
446 }
447
448 /*****************************************************************************
449 *Function name
450 * getTSCPerUsec : calculate cycles per Usec for current block
451 *Input Params
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 */
458
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;
465
466 lttdes->TSCPerUsec = (double)lBufTotalTSC / (double)lBufTotalUSec;
467 }
468
469 /*****************************************************************************
470 *Function name
471 * getEventTime : calculate the time the event occurs
472 *Input Params
473 * lttdes : ltt file descriptor
474 * time_delta : time difference between block header and the event
475 *Output Params
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 */
482
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;
487
488 /* Determine offset in struct timeval */
489 lTimeOffset.tv_usec = (long)lEventUSec % 1000000;
490 lTimeOffset.tv_sec = (long)lEventUSec / 1000000;
491
492 DBTimeAdd((*pTime), lttdes->a_block_header->time, lTimeOffset);
493 }
494
495
496 /*****************************************************************************
497 *Function name
498 * trace_read : get an event from the file
499 *Input Params
500 * lttdes : ltt file descriptor
501 * ev : a structure contains the event
502 *return value
503 * 0 : success
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){
509 int err;
510 int8_t evId;
511 facility_handle * facHandle;
512 uint32_t time_delta;
513 event_handle * eHandle;
514 int8_t * tmp;
515
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
520 }else{
521 if((err=readBlock(lttdes, lttdes->which_block + 1)) != 0) return err;
522 }
523 }
524
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()));
528
529 //get facility handle
530 err = trace_lookup_facility(evId, &facHandle);
531 if(err)return err;
532
533 lttdes->current_event_time = time_delta;
534
535 //ev->recid = ??;
536 getEventTime(lttdes, time_delta, &(ev->time));
537 ev->tsc = time_delta;
538 ev->fHandle = facHandle;
539
540 // ev->event_id = evId - idToFacility[evId]->firstId; /* disable during the test */
541 ev->event_id = evId;
542
543 ev->ip_addr = lttdes->trace_header->ip_addr;
544 ev->CPU_id = lttdes->trace_header->cpuID;
545 // ev->tid = ??;
546 // ev->pid = ??;
547 ev->base_field = &(ev->fHandle->events[ev->event_id]->base_field);
548 ev->data = lttdes->cur_event_pos;
549
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;
557 }
558 else {
559 if(ev->base_field->position == 0) lttdes->cur_event_pos += EVENT_HEADER_SIZE();
560 else{
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++){
564 evId = *tmp;
565 tmp++;
566 }
567 //end
568
569 lttdes->cur_event_pos += ((field_handle *)ev->base_field->array[ev->base_field->position-1])->end_field;
570 }
571 }
572
573
574 lttdes->which_event++;
575
576 //will be delete late, test
577 // print_event( ev);
578
579 return 0;
580 }
581
582 /*****************************************************************************
583 *Function name
584 * trace_update_basefield : update base fields
585 *Input Params
586 * lttdes : ltt file descriptor
587 * baseField : base field of the event
588 ****************************************************************************/
589 void trace_update_basefield(ltt_descriptor * lttdes, sequence * baseField){
590 int i,j;
591 char ch;
592 field_handle * fHandle;
593 void* curPos ;
594 off_t offset = EVENT_HEADER_SIZE(); // id and time delta
595 data_type dt, edt;
596 int fixSize = 1; //by default, no string or sequence
597
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;
608 if(dt == SEQUENCE){
609 fixSize = 0;
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)); //
614 }
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;
622 if(dt ==SEQUENCE){
623 curPos += fHandle->sequence_size;
624 offset += fHandle->sequence_size;
625 }
626 if(fixSize) fixSize = 0;
627 for(j=0;j<fHandle->nbElements;j++){
628 while(1){
629 ch = *(char*)(curPos);
630 offset++;
631 curPos++;
632 if(ch == '\0') break; //string ended with '\0'
633 }
634 }
635 fHandle->end_field = offset;
636 }else if(edt == ARRAY || edt == SEQUENCE || edt == STRUCT){ // not supported
637 }
638 }else if(dt == STRING){
639 if(fixSize) fixSize = 0;
640 fHandle->offset = offset;
641 while(1){
642 ch = *(char*)(curPos);
643 offset++;
644 curPos++;
645 if(ch == '\0') break; //string ended with '\0'
646 }
647 fHandle->end_field = offset;
648 }else if (dt == STRUCT){ //not supported
649 }
650 }
651
652 // lttdes->cur_event_pos = (void*)(&fHandle->end_field);
653 lttdes->cur_event_pos += fHandle->end_field;
654 }
655
656 /****************************************************************************
657 *Function name
658 * trace_lookup_facility: get the facility handle
659 *Input Params
660 * facilityName : facility name
661 *Output Params
662 * facHandle : facility handle
663 *return value
664 * 0 : success
665 * EINVAL : registered facility is not the same one used here
666 ****************************************************************************/
667 int trace_lookup_facility(int evId, facility_handle ** facHandle){
668 int i;
669 facility_handle * fHandle;
670
671 for(i=0;i<facilities.position;i++){
672 fHandle = (facility_handle *)facilities.array[i];
673
674 /* disable during the test */
675 *facHandle = fHandle;
676 return 0;
677 /*
678 if(strcmp(idToFacility[evId]->name, fHandle->name)==0){
679 if(idToFacility[evId]->checksum != fHandle->checksum)
680 return EINVAL;
681 *facHandle = fHandle;
682 return 0;
683 }
684 */
685 }
686
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];
691
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 */
694
695 *facHandle = fHandle;
696
697 return 0;
698 }
699
700 /****************************************************************************
701 *Function name
702 * trace_lookup_event: get the event handle
703 *Input Params
704 * event_id : id of event in the facility
705 * facHandle : facility handle containing an array of event handle
706 *Output Params
707 * eventHandle : event handle
708 *return value
709 * 0 : success
710 ****************************************************************************/
711 int trace_lookup_event(int event_id, facility_handle * facHandle, event_handle ** eventHandle){
712 *eventHandle = facHandle->events[event_id];
713 return 0;
714 }
715
716 /****************************************************************************
717 *Function name
718 * trace_lookup_field: get field handle
719 *Input Params
720 * baseField : a sequence of field handles
721 * position : the position of the field handle in the baseField
722 *Output Params
723 * fieldHandle : field handle
724 *return value
725 * 0 : success
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];
731 return 0;
732 }
733
734 /****************************************************************************
735 *Function name
736 * readFile : wrap function to read from a file
737 *Input Params
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
742 *return value
743 * 0 : success
744 * EIO : can not read from the file
745 ****************************************************************************/
746 int readFile(int fd, void * buf, size_t size, char * mesg){
747 ssize_t nbBytes;
748 nbBytes = read(fd, buf, size);
749 if(nbBytes != size){
750 printf("%s\n",mesg);
751 return EIO;
752 }
753 return 0;
754 }
755
756 /****************************************************************************
757 *Function name
758 * trace_seek : seek according to event
759 *Input Params
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
763 *return value
764 * 0 : success
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;
772 event_struct ev;
773
774 if(whence == SEEK_CUR && offset == 0)return 0;
775
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
789 if(offset < 0){
790 newOffset = lttdes->which_event + offset;
791 updateLttdes(lttdes);
792 if(lttdes->which_block == 1){
793 newOffset--;
794 if(newOffset < 0) return 0; //at the beginning of the file
795 }
796 }
797 }
798
799 //seek the right position of the event
800 if(newOffset > 0){
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;
805 }
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--;
812 }
813 }
814
815 j = lttdes->which_event;
816 for(i=j;i<j+newOffset;i++){
817 err = trace_read(lttdes,&ev);
818 if(err) return err;
819 }
820
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;
825
826 return 0;
827 }
828
829 /****************************************************************************
830 *Function name
831 * readBlock : read a block from the file
832 *Input Params
833 * lttdes : ltt file descriptor
834 * whichBlock : the block which will be read
835 *return value
836 * 0 : success
837 * EINVAL : lseek fail
838 * EIO : can not read from the file
839 ****************************************************************************/
840 int readBlock(ltt_descriptor * lttdes, int whichBlock){
841 off_t nbBytes;
842 nbBytes = lseek(lttdes->fd, (off_t)((whichBlock-1)*lttdes->trace_header->buffer_size),SEEK_SET);
843 if(nbBytes == -1) return EINVAL;
844
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);
854 }
855 lttdes->cur_event_pos = lttdes->first_event_pos;
856 lttdes->current_event_time = lttdes->a_block_header->tsc;
857
858 getTSCPerUsec(lttdes);
859
860 return 0;
861 }
862
863 /****************************************************************************
864 *Function name
865 * updateLttdes : update the info of ltt descriptor
866 *Input Params
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;
874 }
875
876 /****************************************************************************
877 *Function name
878 * trace_seek_time : seek according to time
879 *Input Params
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
883 *return value
884 * 0 : success
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;
892 event_struct ev;
893 void * tmpAddr;
894 int whichEvent;
895 uint32_t curEventTime;
896
897 if(whence == SEEK_CUR && offset == 0)return 0;
898
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;
911 }else{
912 curTime = lttdes->current_event_time;
913 }
914
915 seekTime = curTime + offset;
916
917 //find the block which contains the time
918 if(offset>0){
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);
923 }else if(offset<0){
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);
928 }else{
929 if(whence == SEEK_SET) blockNum = 1;
930 if(whence == SEEK_END) blockNum = lttdes->nbBlocks;
931 }
932
933 if(blockNum < 0) return -blockNum;
934
935 //get the block
936 if(lttdes->which_block != blockNum){
937 if((err=readBlock(lttdes,blockNum))!=0) return err;
938 }else updateLttdes(lttdes);
939
940 if(lttdes->a_block_footer->tsc <= seekTime){
941 if(blockNum == lttdes->nbBlocks) return ENOENT; // end of file
942 blockNum++;
943 }
944
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;
948 }
949
950 if(lttdes->current_event_time >= seekTime ) return 0; //find the right place
951
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;
963 return 0;
964 }
965 }
966
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;
970
971 return 0;
972 }
973
974 /****************************************************************************
975 *Function name
976 * trace_get_time_block_position : get the position of the block which
977 * contains the seekTime
978 *Input Params
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
983 *return value
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;
991
992 if(beginBlock == endBlock)return -beginBlock;
993
994 //get the start time of the block
995 if(lttdes->which_block != middleBlock){
996 if((err=readBlock(lttdes,middleBlock))!=0) return err;
997 }else{
998 updateLttdes(lttdes);
999 }
1000
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);
1004 }
1005
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);
1009 }
1010
1011 /****************************************************************************
1012 *Function names
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
1017 * binary data
1018 *Input Params
1019 * field : field handle
1020 * data : event binary data
1021 *return value
1022 * corresponding data type
1023 ****************************************************************************/
1024 int trace_get_char(field_handle * field, void * data){
1025 return (int)(*(char*)(data + field->offset));
1026 }
1027
1028 int trace_get_uchar(field_handle * field, void * data){
1029 return (int)(*(unsigned char*)(data + field->offset));
1030 }
1031
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);
1037 }
1038
1039 short int trace_get_short(field_handle * field, void * data){
1040 return *(short int*)(data + field->offset);
1041 }
1042
1043 unsigned short int trace_get_ushort(field_handle * field, void * data){
1044 return *(unsigned short int*)(data + field->offset);
1045 }
1046
1047 int trace_get_integer(field_handle * field, void * data){
1048 return *(int*)(data + field->offset);
1049 }
1050
1051 unsigned int trace_get_uinteger(field_handle * field, void * data){
1052 return *(unsigned int*)(data + field->offset);
1053 }
1054
1055 long trace_get_long(field_handle * field, void * data){
1056 return *(long*)(data + field->offset);
1057 }
1058
1059 unsigned long trace_get_ulong(field_handle * field, void * data){
1060 return *(unsigned long*)(data + field->offset);
1061 }
1062
1063 float trace_get_float(field_handle * field, void * data){
1064 return *(float*)(data + field->offset);
1065 }
1066
1067 double trace_get_double(field_handle * field, void * data){
1068 return *(double*)(data + field->offset);
1069 }
1070
1071 char * trace_get_string(field_handle * field, void * data){
1072 return allocAndCopy((char*)(data + field->offset));
1073 }
1074
1075
1076 //main and the following functions are just for the purpose of test, it will be deleted late
1077
1078 int main(char * argc, char ** argv){
1079 int i,j,k, err;
1080 facility_handle * fH;
1081 event_handle *evH;
1082 field_handle *fldH;
1083 int fd;
1084 block_header bh;
1085 block_footer bf, *ptr;
1086 trace_header_event thev;
1087 ltt_descriptor * lttdes;
1088
1089 char buf[BUFFER_SIZE];
1090
1091 fp = fopen("statistic","w");
1092 if(!fp) {
1093 printf("can not open test file\n");
1094 exit(1);
1095 }
1096
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);
1101 }
1102 ptr = (block_footer *)(lttdes->buffer + lttdes->trace_header->buffer_size - sizeof(block_footer));
1103
1104 /*
1105 err = trace_seek_time(lttdes, 11, SEEK_SET);
1106 err = trace_seek_time(lttdes, 1060000000, SEEK_CUR);
1107 while(1){
1108 err = trace_seek_time(lttdes, 100000000, SEEK_CUR);
1109 if(err) break;
1110 }
1111 */
1112 }
This page took 0.059014 seconds and 4 git commands to generate.