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