git-svn-id: http://ltt.polymtl.ca/svn@150 04897980-b3bd-0310-b5e0-8ef037075253
[lttv.git] / ltt / branches / poly / ltt / tracefile.c
1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <sys/stat.h>
4 #include <sys/types.h>
5 #include <dirent.h>
6 #include <linux/errno.h>
7
8 #include <ltt/LTTTypes.h>
9 #include "parser.h"
10 #include <ltt/trace.h>
11
12 #define DIR_NAME_SIZE 256
13
14 /* set the offset of the fields belonging to the event,
15 need the information of the archecture */
16 void setFieldsOffset(LttTracefile *tf,LttEventType *evT,void *evD,LttTrace *t);
17
18 /* get the size of the field type according to the archtecture's
19 size and endian type(info of the archecture) */
20 int getFieldtypeSize(LttTracefile * tf, LttEventType * evT, int offsetRoot,
21 int offsetParent, LttField *fld, void *evD, LttTrace* t);
22
23 /* read a fixed size or a block information from the file (fd) */
24 int readFile(int fd, void * buf, size_t size, char * mesg);
25 int readBlock(LttTracefile * tf, int whichBlock);
26
27 /* calculate cycles per nsec for current block */
28 void getCyclePerNsec(LttTracefile * t);
29
30 /* reinitialize the info of the block which is already in the buffer */
31 void updateTracefile(LttTracefile * tf);
32
33 /* go to the next event */
34 int skipEvent(LttTracefile * t);
35
36 /* compare two time (LttTime), 0:t1=t2, -1:t1<t2, 1:t1>t2 */
37 int timecmp(LttTime * t1, LttTime * t2);
38
39 /* get an integer number */
40 int getIntNumber(int size1, void *evD);
41
42
43
44 /*****************************************************************************
45 *Function name
46 * ltt_tracefile_open : open a trace file, construct a LttTracefile
47 *Input params
48 * t : the trace containing the tracefile
49 * fileName : path name of the trace file
50 *Return value
51 * : a pointer to a tracefile
52 ****************************************************************************/
53
54 LttTracefile* ltt_tracefile_open(LttTrace * t, char * fileName)
55 {
56 LttTracefile * tf;
57 struct stat lTDFStat; /* Trace data file status */
58 BlockStart a_block_start;
59
60 tf = g_new(LttTracefile, 1);
61
62 //open the file
63 tf->name = g_strdup(fileName);
64 tf->trace = t;
65 tf->fd = open(fileName, O_RDONLY, 0);
66 if(tf->fd < 0){
67 g_error("Unable to open input data file %s\n", fileName);
68 }
69
70 // Get the file's status
71 if(fstat(tf->fd, &lTDFStat) < 0){
72 g_error("Unable to get the status of the input data file %s\n", fileName);
73 }
74
75 // Is the file large enough to contain a trace
76 if(lTDFStat.st_size < sizeof(BlockStart) + EVENT_HEADER_SIZE){
77 g_print("The input data file %s does not contain a trace\n", fileName);
78 g_free(tf->name);
79 close(tf->fd);
80 g_free(tf);
81 return NULL;
82 }
83
84 //store the size of the file
85 tf->file_size = lTDFStat.st_size;
86 tf->block_size = t->system_description->ltt_block_size;
87 tf->block_number = tf->file_size / tf->block_size;
88 tf->which_block = 0;
89
90 //allocate memory to contain the info of a block
91 tf->buffer = (void *) g_new(char, t->system_description->ltt_block_size);
92
93 //read the first block
94 if(readBlock(tf,1)) exit(1);
95
96 return tf;
97 }
98
99
100 /*****************************************************************************
101 *Open control and per cpu tracefiles
102 ****************************************************************************/
103
104 void ltt_tracefile_open_cpu(LttTrace *t, char * tracefile_name)
105 {
106 LttTracefile * tf;
107 tf = ltt_tracefile_open(t,tracefile_name);
108 if(!tf) return;
109 t->per_cpu_tracefile_number++;
110 g_ptr_array_add(t->per_cpu_tracefiles, tf);
111 }
112
113 void ltt_tracefile_open_control(LttTrace *t, char * control_name)
114 {
115 LttTracefile * tf;
116 LttEvent * ev;
117 LttFacility * f;
118 uint16_t evId;
119 void * pos;
120 FacilityLoad fLoad;
121 int i;
122
123 tf = ltt_tracefile_open(t,control_name);
124 if(!tf) return;
125 t->control_tracefile_number++;
126 g_ptr_array_add(t->control_tracefiles,tf);
127
128 //parse facilities tracefile to get base_id
129 if(strcmp(&control_name[strlen(control_name)-10],"facilities") ==0){
130 while(1){
131 ev = ltt_tracefile_read(tf);
132 if(!ev)return; // end of file
133
134 if(ev->event_id == TRACE_FACILITY_LOAD){
135 pos = ev->data;
136 fLoad.name = (char*)pos;
137 fLoad.checksum = *(LttChecksum*)(pos + strlen(fLoad.name));
138 fLoad.base_code = *(uint32_t*)(pos + strlen(fLoad.name) + sizeof(LttChecksum));
139
140 for(i=0;i<t->facility_number;i++){
141 f = (LttFacility*)g_ptr_array_index(t->facilities,i);
142 if(strcmp(f->name,fLoad.name)==0 && fLoad.checksum==f->checksum){
143 f->base_id = fLoad.base_code;
144 break;
145 }
146 }
147 if(i==t->facility_number)
148 g_error("Facility: %s, checksum: %d is not founded\n",
149 fLoad.name,fLoad.checksum);
150 }else if(ev->event_id == TRACE_BLOCK_START){
151 continue;
152 }else if(ev->event_id == TRACE_BLOCK_END){
153 break;
154 }else g_error("Not valid facilities trace file\n");
155 g_free(ev);
156 }
157 }
158 }
159
160 /*****************************************************************************
161 *Function name
162 * ltt_tracefile_close: close a trace file,
163 *Input params
164 * t : tracefile which will be closed
165 ****************************************************************************/
166
167 void ltt_tracefile_close(LttTracefile *t)
168 {
169 g_free(t->name);
170 g_free(t->buffer);
171 close(t->fd);
172 g_free(t);
173 }
174
175
176 /*****************************************************************************
177 *Get system information
178 ****************************************************************************/
179 void getSystemInfo(LttSystemDescription* des, char * pathname)
180 {
181 FILE * fp;
182 int i;
183 int entry_number = 15;
184 char buf[DIR_NAME_SIZE];
185 char description[4*DIR_NAME_SIZE];
186 char * ptr;
187
188 fp = fopen(pathname,"r");
189 if(!fp){
190 g_error("Can not open file : %s\n", pathname);
191 }
192
193 while(fgets(buf,DIR_NAME_SIZE, fp)!= NULL){
194 ptr = buf;
195 while(isspace(*ptr)) ptr++;
196 if(strlen(ptr) == 0) continue;
197 break;
198 }
199
200 if(strlen(ptr) == 0) g_error("Not a valid file: %s\n", pathname);
201 if(strncmp("<system",ptr,7) !=0)g_error("Not a valid file: %s\n", pathname);
202
203 for(i=0;i<entry_number;i++){
204 if(fgets(buf,DIR_NAME_SIZE, fp)== NULL)
205 g_error("Not a valid file: %s\n", pathname);
206 buf[strlen(buf)-1] = '\0';
207 ptr = buf;
208 while(isspace(*ptr)) ptr++;
209 switch(i){
210 case 0:
211 if(strncmp("node_name=",ptr,10)!=0)
212 g_error("Not a valid file: %s\n", pathname);
213 des->node_name = g_strdup(ptr+10);
214 break;
215 case 1:
216 if(strncmp("domainname=",ptr,11)!=0)
217 g_error("Not a valid file: %s\n", pathname);
218 des->domain_name = g_strdup(ptr+11);
219 break;
220 case 2:
221 if(strncmp("cpu=",ptr,4)!=0)
222 g_error("Not a valid file: %s\n", pathname);
223 des->nb_cpu = (unsigned)atoi(ptr+4);
224 break;
225 case 3:
226 if(strncmp("arch_size=",ptr,10)!=0)
227 g_error("Not a valid file: %s\n", pathname);
228 if(strcmp(ptr+10,"\"LP32\"") == 0) des->size = LTT_LP32;
229 else if(strcmp(ptr+10,"\"ILP32\"") == 0) des->size = LTT_ILP32;
230 else if(strcmp(ptr+10,"\"LP64\"") == 0) des->size = LTT_LP64;
231 else if(strcmp(ptr+10,"\"ILP64\"") == 0) des->size = LTT_ILP64;
232 else if(strcmp(ptr+10,"\"UNKNOWN\"") == 0) des->size = LTT_UNKNOWN;
233 break;
234 case 4:
235 if(strncmp("endian=",ptr,7)!=0)
236 g_error("Not a valid file: %s\n", pathname);
237 if(strcmp(ptr+7,"\"LITTLE_ENDIAN\"") == 0)
238 des->endian = LTT_LITTLE_ENDIAN;
239 else if(strcmp(ptr+7,"\"BIG_ENDIAN\"") == 0)
240 des->endian = LTT_BIG_ENDIAN;
241 break;
242 case 5:
243 if(strncmp("kernel_name=",ptr,12)!=0)
244 g_error("Not a valid file: %s\n", pathname);
245 des->kernel_name = g_strdup(ptr+12);
246 break;
247 case 6:
248 if(strncmp("kernel_release=",ptr,15)!=0)
249 g_error("Not a valid file: %s\n", pathname);
250 des->kernel_release = g_strdup(ptr+15);
251 break;
252 case 7:
253 if(strncmp("kernel_version=",ptr,15)!=0)
254 g_error("Not a valid file: %s\n", pathname);
255 des->kernel_version = g_strdup(ptr+15);
256 break;
257 case 8:
258 if(strncmp("machine=",ptr,8)!=0)
259 g_error("Not a valid file: %s\n", pathname);
260 des->machine = g_strdup(ptr+8);
261 break;
262 case 9:
263 if(strncmp("processor=",ptr,10)!=0)
264 g_error("Not a valid file: %s\n", pathname);
265 des->processor = g_strdup(ptr+10);
266 break;
267 case 10:
268 if(strncmp("hardware_platform=",ptr,18)!=0)
269 g_error("Not a valid file: %s\n", pathname);
270 des->hardware_platform = g_strdup(ptr+18);
271 break;
272 case 11:
273 if(strncmp("operating_system=",ptr,17)!=0)
274 g_error("Not a valid file: %s\n", pathname);
275 des->operating_system = g_strdup(ptr+17);
276 break;
277 case 12:
278 if(strncmp("ltt_major_version=",ptr,18)!=0)
279 g_error("Not a valid file: %s\n", pathname);
280 ptr += 18;
281 // ptr++;//skip begining "
282 // ptr[strlen(ptr)-1] = '\0'; //get rid of the ending "
283 des->ltt_major_version = (unsigned)atoi(ptr);
284 break;
285 case 13:
286 if(strncmp("ltt_minor_version=",ptr,18)!=0)
287 g_error("Not a valid file: %s\n", pathname);
288 ptr += 18;
289 // ptr++;//skip begining "
290 // ptr[strlen(ptr)-1] = '\0'; //get rid of the ending "
291 des->ltt_minor_version = (unsigned)atoi(ptr);
292 break;
293 case 14:
294 if(strncmp("ltt_block_size=",ptr,15)!=0)
295 g_error("Not a valid file: %s\n", pathname);
296 ptr += 15;
297 // ptr++;//skip begining "
298 // ptr[strlen(ptr)-1] = '\0'; //get rid of the ending "
299 des->ltt_block_size = (unsigned)atoi(ptr);
300 break;
301 default:
302 g_error("Not a valid file: %s\n", pathname);
303 }
304 }
305
306 //get description
307 description[0] = '\0';
308 if(fgets(buf,DIR_NAME_SIZE, fp)== NULL)
309 g_error("Not a valid file: %s\n", pathname);
310 ptr = buf;
311 while(isspace(*ptr)) ptr++;
312 if(*ptr != '>') g_error("Not a valid file: %s\n", pathname);
313 while((ptr=fgets(buf,DIR_NAME_SIZE, fp))!= NULL){
314 ptr = buf;
315 while(isspace(*ptr)) ptr++;
316 if(strncmp("</system>",ptr,9) == 0 )break;
317 strcat(description, buf);
318 }
319 if(!ptr)g_error("Not a valid file: %s\n", pathname);
320 if(description[0] = '\0')des->description = NULL;
321 des->description = g_strdup(description);
322
323 fclose(fp);
324 }
325
326 /*****************************************************************************
327 *The following functions get facility/tracefile information
328 ****************************************************************************/
329
330 void getFacilityInfo(LttTrace *t, char* eventdefs)
331 {
332 DIR * dir;
333 struct dirent *entry;
334 char * ptr;
335 int i,j;
336 LttFacility * f;
337 LttEventType * et;
338 char name[DIR_NAME_SIZE];
339
340 dir = opendir(eventdefs);
341 if(!dir) g_error("Can not open directory: %s\n", eventdefs);
342
343 while((entry = readdir(dir)) != NULL){
344 ptr = &entry->d_name[strlen(entry->d_name)-4];
345 if(strcmp(ptr,".xml") != 0) continue;
346 strcpy(name,eventdefs);
347 strcat(name,entry->d_name);
348 ltt_facility_open(t,name);
349 }
350 closedir(dir);
351
352 for(j=0;j<t->facility_number;j++){
353 f = (LttFacility*)g_ptr_array_index(t->facilities, j);
354 for(i=0; i<f->event_number; i++){
355 et = f->events[i];
356 setFieldsOffset(NULL, et, NULL, t);
357 }
358 }
359 }
360
361 void getControlFileInfo(LttTrace *t, char* control)
362 {
363 DIR * dir;
364 struct dirent *entry;
365 char name[DIR_NAME_SIZE];
366
367 dir = opendir(control);
368 if(!dir) g_error("Can not open directory: %s\n", control);
369
370 while((entry = readdir(dir)) != NULL){
371 if(strcmp(entry->d_name,"facilities") != 0 &&
372 strcmp(entry->d_name,"interrupts") != 0 &&
373 strcmp(entry->d_name,"processes") != 0) continue;
374
375 strcpy(name,control);
376 strcat(name,entry->d_name);
377 ltt_tracefile_open_control(t,name);
378 }
379 closedir(dir);
380 }
381
382 void getCpuFileInfo(LttTrace *t, char* cpu)
383 {
384 DIR * dir;
385 struct dirent *entry;
386 char name[DIR_NAME_SIZE];
387
388 dir = opendir(cpu);
389 if(!dir) g_error("Can not open directory: %s\n", cpu);
390
391 while((entry = readdir(dir)) != NULL){
392 if(strcmp(entry->d_name,".") != 0 &&
393 strcmp(entry->d_name,"..") != 0 ){
394 strcpy(name,cpu);
395 strcat(name,entry->d_name);
396 ltt_tracefile_open_cpu(t,name);
397 }else continue;
398 }
399 closedir(dir);
400 }
401
402 /*****************************************************************************
403 *A trace is specified as a pathname to the directory containing all the
404 *associated data (control tracefiles, per cpu tracefiles, event
405 *descriptions...).
406 *
407 *When a trace is closed, all the associated facilities, types and fields
408 *are released as well.
409 ****************************************************************************/
410
411 LttTrace *ltt_trace_open(char *pathname)
412 {
413 LttTrace * t;
414 LttSystemDescription * sys_description;
415 char eventdefs[DIR_NAME_SIZE];
416 char info[DIR_NAME_SIZE];
417 char control[DIR_NAME_SIZE];
418 char cpu[DIR_NAME_SIZE];
419 char tmp[DIR_NAME_SIZE];
420 gboolean has_slash = FALSE;
421
422 //establish the pathname to different directories
423 if(pathname[strlen(pathname)-1] == '/')has_slash = TRUE;
424 strcpy(eventdefs,pathname);
425 if(!has_slash)strcat(eventdefs,"/");
426 strcat(eventdefs,"eventdefs/");
427
428 strcpy(info,pathname);
429 if(!has_slash)strcat(info,"/");
430 strcat(info,"info/");
431
432 strcpy(control,pathname);
433 if(!has_slash)strcat(control,"/");
434 strcat(control,"control/");
435
436 strcpy(cpu,pathname);
437 if(!has_slash)strcat(cpu,"/");
438 strcat(cpu,"cpu/");
439
440 //new trace
441 t = g_new(LttTrace, 1);
442 sys_description = g_new(LttSystemDescription, 1);
443 t->pathname = g_strdup(pathname);
444 t->facility_number = 0;
445 t->control_tracefile_number = 0;
446 t->per_cpu_tracefile_number = 0;
447 t->system_description = sys_description;
448 t->control_tracefiles = g_ptr_array_new();
449 t->per_cpu_tracefiles = g_ptr_array_new();
450 t->facilities = g_ptr_array_new();
451 getDataEndianType(&(t->my_arch_size), &(t->my_arch_endian));
452
453 //get system description
454 strcpy(tmp,info);
455 strcat(tmp,"system.xml");
456 getSystemInfo(sys_description, tmp);
457
458 //get facilities info
459 getFacilityInfo(t,eventdefs);
460
461 //get control tracefile info
462 getControlFileInfo(t,control);
463
464 //get cpu tracefile info
465 getCpuFileInfo(t,cpu);
466
467 return t;
468 }
469
470 void ltt_trace_close(LttTrace *t)
471 {
472 int i;
473 LttTracefile * tf;
474 LttFacility * f;
475
476 g_free(t->pathname);
477
478 //free system_description
479 g_free(t->system_description->description);
480 g_free(t->system_description->node_name);
481 g_free(t->system_description->domain_name);
482 g_free(t->system_description->kernel_name);
483 g_free(t->system_description->kernel_release);
484 g_free(t->system_description->kernel_version);
485 g_free(t->system_description->machine);
486 g_free(t->system_description->processor);
487 g_free(t->system_description->hardware_platform);
488 g_free(t->system_description->operating_system);
489 g_free(t->system_description);
490
491 //free control_tracefiles
492 for(i=0;i<t->control_tracefile_number;i++){
493 tf = (LttTracefile*)g_ptr_array_index(t->control_tracefiles,i);
494 ltt_tracefile_close(tf);
495 }
496 g_ptr_array_free(t->control_tracefiles, TRUE);
497
498 //free per_cpu_tracefiles
499 for(i=0;i<t->per_cpu_tracefile_number;i++){
500 tf = (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles,i);
501 ltt_tracefile_close(tf);
502 }
503 g_ptr_array_free(t->per_cpu_tracefiles, TRUE);
504
505 //free facilities
506 for(i=0;i<t->facility_number;i++){
507 f = (LttFacility*)g_ptr_array_index(t->facilities,i);
508 ltt_facility_close(f);
509 }
510 g_ptr_array_free(t->facilities, TRUE);
511
512 g_free(t);
513
514 g_blow_chunks();
515 }
516
517
518 /*****************************************************************************
519 *Get the system description of the trace
520 ****************************************************************************/
521
522 LttSystemDescription *ltt_trace_system_description(LttTrace *t)
523 {
524 return t->system_description;
525 }
526
527 /*****************************************************************************
528 * The following functions discover the facilities of the trace
529 ****************************************************************************/
530
531 unsigned ltt_trace_facility_number(LttTrace *t)
532 {
533 return (unsigned)(t->facility_number);
534 }
535
536 LttFacility *ltt_trace_facility_get(LttTrace *t, unsigned i)
537 {
538 return (LttFacility*)g_ptr_array_index(t->facilities, i);
539 }
540
541 /*****************************************************************************
542 *Function name
543 * ltt_trace_facility_find : find facilities in the trace
544 *Input params
545 * t : the trace
546 * name : facility name
547 *Output params
548 * position : position of the facility in the trace
549 *Return value
550 * : the number of facilities
551 ****************************************************************************/
552
553 unsigned ltt_trace_facility_find(LttTrace *t, char *name, unsigned *position)
554 {
555 int i, count=0;
556 LttFacility * f;
557 for(i=0;i=t->facility_number;i++){
558 f = (LttFacility*)g_ptr_array_index(t->facilities, i);
559 if(strcmp(f->name,name)==0){
560 count++;
561 if(count==1) *position = i;
562 }else{
563 if(count) break;
564 }
565 }
566 return count;
567 }
568
569 /*****************************************************************************
570 * Functions to discover all the event types in the trace
571 ****************************************************************************/
572
573 unsigned ltt_trace_eventtype_number(LttTrace *t)
574 {
575 int i;
576 unsigned count = 0;
577 LttFacility * f;
578 for(i=0;i=t->facility_number;i++){
579 f = (LttFacility*)g_ptr_array_index(t->facilities, i);
580 count += f->event_number;
581 }
582 return count;
583 }
584
585 LttFacility * ltt_trace_facility_by_id(LttTrace * trace, unsigned id)
586 {
587 LttFacility * facility;
588 int i;
589 for(i=0;i<trace->facility_number;i++){
590 facility = (LttFacility*) g_ptr_array_index(trace->facilities,i);
591 if(id >= facility->base_id &&
592 id < facility->base_id + facility->event_number)
593 break;
594 }
595 if(i==trace->facility_number) return NULL;
596 else return facility;
597 }
598
599 LttEventType *ltt_trace_eventtype_get(LttTrace *t, unsigned evId)
600 {
601 LttFacility * f;
602 f = ltt_trace_facility_by_id(t,evId);
603 if(!f) return NULL;
604 return f->events[evId - f->base_id];
605 }
606
607 /*****************************************************************************
608 *There is one "per cpu" tracefile for each CPU, numbered from 0 to
609 *the maximum number of CPU in the system. When the number of CPU installed
610 *is less than the maximum, some positions are unused. There are also a
611 *number of "control" tracefiles (facilities, interrupts...).
612 ****************************************************************************/
613 unsigned ltt_trace_control_tracefile_number(LttTrace *t)
614 {
615 return t->control_tracefile_number;
616 }
617
618 unsigned ltt_trace_per_cpu_tracefile_number(LttTrace *t)
619 {
620 return t->per_cpu_tracefile_number;
621 }
622
623 /*****************************************************************************
624 *It is possible to search for the tracefiles by name or by CPU position.
625 *The index within the tracefiles of the same type is returned if found
626 *and a negative value otherwise.
627 ****************************************************************************/
628
629 int ltt_trace_control_tracefile_find(LttTrace *t, char *name)
630 {
631 LttTracefile * tracefile;
632 int i;
633 for(i=0;i<t->control_tracefile_number;i++){
634 tracefile = (LttTracefile*)g_ptr_array_index(t->control_tracefiles, i);
635 if(strcmp(tracefile->name, name)==0)break;
636 }
637 if(i == t->control_tracefile_number) return -1;
638 return i;
639 }
640
641 int ltt_trace_per_cpu_tracefile_find(LttTrace *t, unsigned i)
642 {
643 LttTracefile * tracefile;
644 int j, name;
645 for(j=0;j<t->per_cpu_tracefile_number;j++){
646 tracefile = (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles, j);
647 name = atoi(tracefile->name);
648 if(name == (int)i)break;
649 }
650 if(j == t->per_cpu_tracefile_number) return -1;
651 return j;
652 }
653
654 /*****************************************************************************
655 *Get a specific tracefile
656 ****************************************************************************/
657
658 LttTracefile *ltt_trace_control_tracefile_get(LttTrace *t, unsigned i)
659 {
660 return (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles, i);
661 }
662
663 LttTracefile *ltt_trace_per_cpu_tracefile_get(LttTrace *t, unsigned i)
664 {
665 return (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles, i);
666 }
667
668 /*****************************************************************************
669 *Get the name of a tracefile
670 ****************************************************************************/
671
672 char *ltt_tracefile_name(LttTracefile *tf)
673 {
674 return tf->name;
675 }
676
677 /*****************************************************************************
678 *Function name
679 * ltt_tracefile_seek_time: seek to the first event of the trace with time
680 * larger or equal to time
681 *Input params
682 * t : tracefile
683 * time : criteria of the time
684 ****************************************************************************/
685
686 void ltt_tracefile_seek_time(LttTracefile *t, LttTime time)
687 {
688 int err;
689 LttTime lttTime;
690 int headTime = timecmp(&(t->a_block_start->time), &time);
691 int tailTime = timecmp(&(t->a_block_end->time), &time);
692 LttEvent * ev;
693
694 if(headTime < 0 && tailTime > 0){
695 lttTime = getEventTime(t);
696 err = timecmp(&lttTime, &time);
697 if(err > 0){
698 if(t->which_event==2 || timecmp(&t->prev_event_time,&time)<0){
699 return;
700 }else{
701 updateTracefile(t);
702 return ltt_tracefile_seek_time(t, time);
703 }
704 }else if(err < 0){
705 while(1){
706 ev = ltt_tracefile_read(t);
707 if(ev == NULL){
708 g_print("End of file\n");
709 return;
710 }
711 g_free(ev);
712 lttTime = getEventTime(t);
713 err = timecmp(&lttTime, &time);
714 if(err >= 0)return;
715 }
716 }else return;
717 }else if(headTime > 0){
718 if(t->which_block == 1){
719 updateTracefile(t);
720 }else{
721 if(timecmp(&(t->prev_block_end_time),&time) >= 0 ){
722 err=readBlock(t,t->which_block-1);
723 if(err) g_error("Can not read tracefile: %s\n", t->name);
724 return ltt_tracefile_seek_time(t, time) ;
725 }else{
726 updateTracefile(t);
727 }
728 }
729 }else if(tailTime < 0){
730 if(t->which_block != t->block_number){
731 err=readBlock(t,t->which_block+1);
732 if(err) g_error("Can not read tracefile: %s\n", t->name);
733 }else {
734 g_print("End of file\n");
735 return;
736 }
737 if(tailTime < 0) return ltt_tracefile_seek_time(t, time);
738 }else if(headTime == 0){
739 updateTracefile(t);
740 }else if(tailTime == 0){
741 t->cur_event_pos = t->a_block_end - EVENT_HEADER_SIZE;
742 t->current_event_time = time;
743 t->cur_heart_beat_number = 0;
744 t->prev_event_time.tv_sec = 0;
745 t->prev_event_time.tv_nsec = 0;
746 return;
747 }
748 }
749
750 /*****************************************************************************
751 *Function name
752 * ltt_tracefile_read : read the current event, set the pointer to the next
753 *Input params
754 * t : tracefile
755 *Return value
756 * LttEvent * : an event to be processed
757 ****************************************************************************/
758
759 LttEvent *ltt_tracefile_read(LttTracefile *t)
760 {
761 LttEvent * lttEvent = (LttEvent *)g_new(LttEvent, 1);
762 int err;
763
764 lttEvent->event_id = (int)(*(uint16_t *)(t->cur_event_pos));
765 if(lttEvent->event_id == TRACE_TIME_HEARTBEAT)
766 t->cur_heart_beat_number++;
767
768 t->prev_event_time = t->current_event_time;
769 // t->current_event_time = getEventTime(t);
770
771 lttEvent->time_delta = *(uint32_t*)(t->cur_event_pos + EVENT_ID_SIZE);
772 lttEvent->event_time = t->current_event_time;
773
774 lttEvent->event_cycle_count = ((uint64_t)1)<<32 * t->cur_heart_beat_number
775 + lttEvent->time_delta;
776
777 lttEvent->tracefile = t;
778 lttEvent->data = t->cur_event_pos + EVENT_HEADER_SIZE;
779
780 //update the fields of the current event and go to the next event
781 err = skipEvent(t);
782 if(err == ENOMEM){
783 g_free(lttEvent);
784 return NULL;
785 }
786 if(err == ENOENT) return lttEvent;
787 if(err == ERANGE) g_error("event id is out of range\n");
788 if(err)g_error("Can not read tracefile\n");
789
790 return lttEvent;
791 }
792
793 /****************************************************************************
794 *Function name
795 * readFile : wrap function to read from a file
796 *Input Params
797 * fd : file descriptor
798 * buf : buf to contain the content
799 * size : number of bytes to be read
800 * mesg : message to be printed if some thing goes wrong
801 *return value
802 * 0 : success
803 * EIO : can not read from the file
804 ****************************************************************************/
805
806 int readFile(int fd, void * buf, size_t size, char * mesg)
807 {
808 ssize_t nbBytes;
809 nbBytes = read(fd, buf, size);
810 if(nbBytes != size){
811 printf("%s\n",mesg);
812 return EIO;
813 }
814 return 0;
815 }
816
817 /****************************************************************************
818 *Function name
819 * readBlock : read a block from the file
820 *Input Params
821 * lttdes : ltt trace file
822 * whichBlock : the block which will be read
823 *return value
824 * 0 : success
825 * EINVAL : lseek fail
826 * EIO : can not read from the file
827 ****************************************************************************/
828
829 int readBlock(LttTracefile * tf, int whichBlock)
830 {
831 off_t nbBytes;
832 uint32_t lostSize;
833
834 if(whichBlock - tf->which_block == 1 && tf->which_block != 0){
835 tf->prev_block_end_time = tf->a_block_end->time;
836 tf->prev_event_time = tf->a_block_end->time;
837 }else{
838 tf->prev_block_end_time.tv_sec = 0;
839 tf->prev_block_end_time.tv_nsec = 0;
840 tf->prev_event_time.tv_sec = 0;
841 tf->prev_event_time.tv_nsec = 0;
842 }
843
844 nbBytes=lseek(tf->fd,(off_t)((whichBlock-1)*tf->block_size), SEEK_SET);
845 if(nbBytes == -1) return EINVAL;
846
847 if(readFile(tf->fd,tf->buffer,tf->block_size,"Unable to read a block"))
848 return EIO;
849
850 tf->a_block_start=(BlockStart *) (tf->buffer + EVENT_HEADER_SIZE);
851 lostSize = *(uint32_t*)(tf->buffer + tf->block_size - sizeof(uint32_t));
852 tf->a_block_end=(BlockEnd *)(tf->buffer + tf->block_size -
853 lostSize + EVENT_HEADER_SIZE);
854
855 tf->which_block = whichBlock;
856 tf->which_event = 1;
857 tf->cur_event_pos = tf->buffer;//the beginning of the block, block start ev
858 tf->cur_heart_beat_number = 0;
859
860 getCyclePerNsec(tf);
861
862 tf->current_event_time = getEventTime(tf);
863
864 return 0;
865 }
866
867 /*****************************************************************************
868 *Function name
869 * updateTracefile : reinitialize the info of the block which is already
870 * in the buffer
871 *Input params
872 * tf : tracefile
873 ****************************************************************************/
874
875 void updateTracefile(LttTracefile * tf)
876 {
877 tf->which_event = 1;
878 tf->cur_event_pos = tf->buffer;
879 tf->current_event_time = getEventTime(tf);
880 tf->cur_heart_beat_number = 0;
881
882 tf->prev_event_time.tv_sec = 0;
883 tf->prev_event_time.tv_nsec = 0;
884 }
885
886 /*****************************************************************************
887 *Function name
888 * skipEvent : go to the next event, update the fields of the current event
889 *Input params
890 * t : tracefile
891 *return value
892 * 0 : success
893 * EINVAL : lseek fail
894 * EIO : can not read from the file
895 * ENOMEM : end of file
896 * ENOENT : last event
897 * ERANGE : event id is out of range
898 ****************************************************************************/
899
900 int skipEvent(LttTracefile * t)
901 {
902 int evId, err;
903 void * evData;
904 LttEventType * evT;
905 LttField * rootFld;
906 static int evCount = 0;
907
908 if(evCount){
909 if(t->which_block == t->block_number &&
910 evCount == t->which_event){
911 return ENOMEM;
912 }else evCount = 0;
913 }
914
915 evId = (int)(*(uint16_t *)(t->cur_event_pos));
916 evData = t->cur_event_pos + EVENT_HEADER_SIZE;
917
918 //regard BLOCK_START, END and HEARTBEAT as special case, there are buildin events
919 if(evId != TRACE_BLOCK_START && evId != TRACE_BLOCK_END && evId != TRACE_TIME_HEARTBEAT){
920 evT = ltt_trace_eventtype_get(t->trace,(unsigned)evId);
921
922 if(evT) rootFld = evT->root_field;
923 else return ERANGE;
924
925 if(rootFld){
926 //event has string/sequence or the last event is not the same event
927 if((evT->latest_block!=t->which_block || evT->latest_event!=t->which_event)
928 && rootFld->field_fixed == 0){
929 setFieldsOffset(t, evT, evData, t->trace);
930 }
931 t->cur_event_pos += EVENT_HEADER_SIZE + rootFld->field_size;
932 }else t->cur_event_pos += EVENT_HEADER_SIZE;
933
934 evT->latest_block = t->which_block;
935 evT->latest_event = t->which_event;
936 }else{
937 if(evId == TRACE_BLOCK_START || evId == TRACE_BLOCK_END){
938 t->cur_event_pos += sizeof(BlockStart) + EVENT_HEADER_SIZE;
939 }else{
940 t->cur_event_pos += sizeof(TimeHeartbeat) + EVENT_HEADER_SIZE;
941 }
942 }
943
944 //the next event is in the next block
945 if(evId == TRACE_BLOCK_END){
946 if(t->which_block == t->block_number){
947 t->which_event++;
948 evCount = t->which_event;
949 return ENOENT;
950 }
951 err = readBlock(t, t->which_block + 1);
952 if(err) return err;
953 }else{
954 t->which_event++;
955 t->current_event_time = getEventTime(t);
956 }
957
958 return 0;
959 }
960
961 /*****************************************************************************
962 *Function name
963 * getCyclePerNsec : calculate cycles per nsec for current block
964 *Input Params
965 * t : tracefile
966 ****************************************************************************/
967
968 void getCyclePerNsec(LttTracefile * t)
969 {
970 LttTime lBufTotalTime; /* Total time for this buffer */
971 LttCycleCount lBufTotalNSec; /* Total time for this buffer in nsecs */
972 LttCycleCount lBufTotalCycle;/* Total cycles for this buffer */
973
974 /* Calculate the total time for this buffer */
975 TimeSub(lBufTotalTime,t->a_block_end->time, t->a_block_start->time);
976
977 /* Calculate the total cycles for this bufffer */
978 lBufTotalCycle = t->a_block_end->cycle_count
979 - t->a_block_start->cycle_count;
980
981 /* Convert the total time to nsecs */
982 lBufTotalNSec = lBufTotalTime.tv_sec * 1000000000 + lBufTotalTime.tv_nsec;
983
984 t->cycle_per_nsec = (double)lBufTotalCycle / (double)lBufTotalNSec;
985 }
986
987 /****************************************************************************
988 *Function name
989 * getEventTime : obtain the time of an event
990 *Input params
991 * tf : tracefile
992 *Return value
993 * LttTime : the time of the event
994 ****************************************************************************/
995
996 LttTime getEventTime(LttTracefile * tf)
997 {
998 LttTime time;
999 LttCycleCount cycle_count; // cycle count for the current event
1000 LttCycleCount lEventTotalCycle; // Total cycles from start for event
1001 double lEventNSec; // Total usecs from start for event
1002 LttTime lTimeOffset; // Time offset in struct LttTime
1003 uint16_t evId;
1004
1005 evId = *(uint16_t*)tf->cur_event_pos;
1006 if(evId == TRACE_BLOCK_START)
1007 return tf->a_block_start->time;
1008 else if(evId == TRACE_BLOCK_END)
1009 return tf->a_block_end->time;
1010
1011
1012 // Calculate total time in cycles from start of buffer for this event
1013 cycle_count = (LttCycleCount)*(uint32_t*)(tf->cur_event_pos + EVENT_ID_SIZE);
1014 if(tf->cur_heart_beat_number)
1015 cycle_count += ((uint64_t)1)<<32 * tf->cur_heart_beat_number;
1016 lEventTotalCycle = cycle_count - tf->a_block_start->cycle_count;
1017
1018 // Convert it to nsecs
1019 lEventNSec = lEventTotalCycle / tf->cycle_per_nsec;
1020
1021 // Determine offset in struct LttTime
1022 lTimeOffset.tv_nsec = (long)lEventNSec % 1000000000;
1023 lTimeOffset.tv_sec = (long)lEventNSec / 1000000000;
1024
1025 TimeAdd(time, tf->a_block_start->time, lTimeOffset);
1026
1027 return time;
1028 }
1029
1030 /*****************************************************************************
1031 *Function name
1032 * setFieldsOffset : set offset of the fields
1033 *Input params
1034 * tracefile : opened trace file
1035 * evT : the event type
1036 * evD : event data, it may be NULL
1037 ****************************************************************************/
1038
1039 void setFieldsOffset(LttTracefile *tf,LttEventType *evT,void *evD,LttTrace* t)
1040 {
1041 LttField * rootFld = evT->root_field;
1042 // rootFld->base_address = evD;
1043
1044 if(rootFld)
1045 rootFld->field_size = getFieldtypeSize(tf, evT, 0,0,rootFld, evD,t);
1046 }
1047
1048 /*****************************************************************************
1049 *Function name
1050 * getFieldtypeSize: get the size of the field type (primitive type)
1051 *Input params
1052 * tracefile : opened trace file
1053 * evT : event type
1054 * offsetRoot : offset from the root
1055 * offsetParent : offset from the parrent
1056 * fld : field
1057 * evD : event data, it may be NULL
1058 *Return value
1059 * int : size of the field
1060 ****************************************************************************/
1061
1062 int getFieldtypeSize(LttTracefile * t, LttEventType * evT, int offsetRoot,
1063 int offsetParent, LttField * fld, void *evD, LttTrace *trace)
1064 {
1065 int size, size1, element_number, i, offset1, offset2;
1066 LttType * type = fld->field_type;
1067
1068 if(t){
1069 if(evT->latest_block==t->which_block && evT->latest_event==t->which_event){
1070 return fld->field_size;
1071 }
1072 }
1073
1074 if(fld->field_fixed == 1){
1075 if(fld == evT->root_field) return fld->field_size;
1076 }
1077
1078 if(type->type_class != LTT_STRUCT && type->type_class != LTT_ARRAY &&
1079 type->type_class != LTT_SEQUENCE && type->type_class != LTT_STRING){
1080 if(fld->field_fixed == -1){
1081 size = (int) ltt_type_size(trace, type);
1082 fld->field_fixed = 1;
1083 }else size = fld->field_size;
1084
1085 }else if(type->type_class == LTT_ARRAY){
1086 element_number = (int) type->element_number;
1087 if(fld->field_fixed == -1){
1088 size = getFieldtypeSize(t, evT, offsetRoot,0,fld->child[0], NULL, trace);
1089 if(size == 0){ //has string or sequence
1090 fld->field_fixed = 0;
1091 }else{
1092 fld->field_fixed = 1;
1093 size *= element_number;
1094 }
1095 }else if(fld->field_fixed == 0){// has string or sequence
1096 size = 0;
1097 for(i=0;i<element_number;i++){
1098 size += getFieldtypeSize(t, evT, offsetRoot+size,size,
1099 fld->child[0], evD+size, trace);
1100 }
1101 }else size = fld->field_size;
1102
1103 }else if(type->type_class == LTT_SEQUENCE){
1104 size1 = (int) ltt_type_size(trace, type);
1105 if(fld->field_fixed == -1){
1106 fld->field_fixed = 0;
1107 size = getFieldtypeSize(t, evT, offsetRoot,0,fld->child[0], NULL, trace);
1108 fld->element_size = size;
1109 }else{//0: sequence
1110 element_number = getIntNumber(size1,evD);
1111 type->element_number = element_number;
1112 if(fld->element_size > 0){
1113 size = element_number * fld->element_size;
1114 }else{//sequence has string or sequence
1115 size = 0;
1116 for(i=0;i<element_number;i++){
1117 size += getFieldtypeSize(t, evT, offsetRoot+size+size1,size+size1,
1118 fld->child[0], evD+size+size1, trace);
1119 }
1120 }
1121 size += size1;
1122 }
1123
1124 }else if(type->type_class == LTT_STRING){
1125 size = 0;
1126 if(fld->field_fixed == -1){
1127 fld->field_fixed = 0;
1128 }else{//0: string
1129 size = strlen((char*)evD) + 1; //include end : '\0'
1130 }
1131
1132 }else if(type->type_class == LTT_STRUCT){
1133 element_number = (int) type->element_number;
1134 size = 0;
1135 if(fld->field_fixed == -1){
1136 offset1 = offsetRoot;
1137 offset2 = 0;
1138 for(i=0;i<element_number;i++){
1139 size1=getFieldtypeSize(t, evT,offset1,offset2, fld->child[i], NULL, trace);
1140 if(size1 > 0 && size >= 0){
1141 size += size1;
1142 if(offset1 >= 0) offset1 += size1;
1143 offset2 += size1;
1144 }else{
1145 size = -1;
1146 offset1 = -1;
1147 offset2 = -1;
1148 }
1149 }
1150 if(size == -1){
1151 fld->field_fixed = 0;
1152 size = 0;
1153 }else fld->field_fixed = 1;
1154 }else if(fld->field_fixed == 0){
1155 offset1 = offsetRoot;
1156 offset2 = 0;
1157 for(i=0;i<element_number;i++){
1158 size=getFieldtypeSize(t,evT,offset1,offset2,fld->child[i],evD+offset2, trace);
1159 offset1 += size;
1160 offset2 += size;
1161 }
1162 size = offset2;
1163 }else size = fld->field_size;
1164 }
1165
1166 fld->offset_root = offsetRoot;
1167 fld->offset_parent = offsetParent;
1168 if(!evD){
1169 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
1170 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
1171 }
1172 fld->field_size = size;
1173
1174 return size;
1175 }
1176
1177 /*****************************************************************************
1178 *Function name
1179 * timecmp : compare two time
1180 *Input params
1181 * t1 : first time
1182 * t2 : second time
1183 *Return value
1184 * int : 0: t1 == t2; -1: t1 < t2; 1: t1 > t2
1185 ****************************************************************************/
1186
1187 int timecmp(LttTime * t1, LttTime * t2)
1188 {
1189 LttTime T;
1190 TimeSub(T, *t1, *t2);
1191 if(T.tv_sec == 0 && T.tv_nsec == 0) return 0;
1192 else if(T.tv_sec > 0 || (T.tv_sec==0 && T.tv_nsec > 0)) return 1;
1193 else return -1;
1194 }
1195
1196 /*****************************************************************************
1197 *Function name
1198 * getIntNumber : get an integer number
1199 *Input params
1200 * size : the size of the integer
1201 * evD : the event data
1202 *Return value
1203 * int : an integer
1204 ****************************************************************************/
1205
1206 int getIntNumber(int size, void *evD)
1207 {
1208 int64_t i;
1209 if(size == 1) i = *(int8_t *)evD;
1210 else if(size == 2) i = *(int16_t *)evD;
1211 else if(size == 4) i = *(int32_t *)evD;
1212 else if(size == 8) i = *(int64_t *)evD;
1213
1214 return (int) i;
1215 }
1216
1217 /*****************************************************************************
1218 *Function name
1219 * getDataEndianType : get the data type size and endian type of the local
1220 * machine
1221 *Input params
1222 * size : size of data type
1223 * endian : endian type, little or big
1224 ****************************************************************************/
1225
1226 void getDataEndianType(LttArchSize * size, LttArchEndian * endian)
1227 {
1228 int i = 1;
1229 char c = (char) i;
1230 int sizeInt=sizeof(int), sizeLong=sizeof(long), sizePointer=sizeof(void *);
1231
1232 if(c == 1) *endian = LTT_LITTLE_ENDIAN;
1233 else *endian = LTT_BIG_ENDIAN;
1234
1235 if(sizeInt == 2 && sizeLong == 4 && sizePointer == 4)
1236 *size = LTT_LP32;
1237 else if(sizeInt == 4 && sizeLong == 4 && sizePointer == 4)
1238 *size = LTT_ILP32;
1239 else if(sizeInt == 4 && sizeLong == 8 && sizePointer == 8)
1240 *size = LTT_LP64;
1241 else if(sizeInt == 8 && sizeLong == 8 && sizePointer == 8)
1242 *size = LTT_ILP64;
1243 else *size = LTT_UNKNOWN;
1244 }
1245
This page took 0.076846 seconds and 5 git commands to generate.