5a1bc7d3 |
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 | } |