UTF8 fix
[lttv.git] / ltt / branches / poly / ltt / tracefile.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Xiangxiu Yang, Mathieu Desnoyers
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19 #include <stdio.h>
20 #include <fcntl.h>
21 #include <string.h>
22 #include <dirent.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <math.h>
28 #include <glib/gstdio.h>
29
30 // For realpath
31 #include <limits.h>
32 #include <stdlib.h>
33
34
35 #include "parser.h"
36 #include <ltt/ltt.h>
37 #include "ltt-private.h"
38 #include <ltt/trace.h>
39 #include <ltt/facility.h>
40 #include <ltt/event.h>
41 #include <ltt/type.h>
42 #include <ltt/ltt-types.h>
43
44 #define DIR_NAME_SIZE 256
45 #define __UNUSED__ __attribute__((__unused__))
46
47 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
48 #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
49
50 #define g_close close
51
52 /* obtain the time of an event */
53
54 static inline LttTime getEventTime(LttTracefile * tf);
55
56
57 /* set the offset of the fields belonging to the event,
58 need the information of the archecture */
59 void setFieldsOffset(LttTracefile *tf,LttEventType *evT,void *evD,LttTrace *t);
60
61 /* get the size of the field type according to the archtecture's
62 size and endian type(info of the archecture) */
63 static inline gint getFieldtypeSize(LttTracefile * tf,
64 LttEventType * evT, gint offsetRoot,
65 gint offsetParent, LttField *fld, void *evD, LttTrace* t);
66
67 /* read a fixed size or a block information from the file (fd) */
68 int readFile(int fd, void * buf, size_t size, gchar * mesg);
69 int readBlock(LttTracefile * tf, int whichBlock);
70
71 /* calculate cycles per nsec for current block */
72 void getCyclePerNsec(LttTracefile * t);
73
74 /* reinitialize the info of the block which is already in the buffer */
75 void updateTracefile(LttTracefile * tf);
76
77 /* go to the next event */
78 int skipEvent(LttTracefile * t);
79
80
81 /* Functions to parse system.xml file (using glib xml parser) */
82 static void parser_start_element (GMarkupParseContext __UNUSED__ *context,
83 const gchar *element_name,
84 const gchar **attribute_names,
85 const gchar **attribute_values,
86 gpointer user_data,
87 GError **error)
88 {
89 int i=0;
90 LttSystemDescription* des = (LttSystemDescription* )user_data;
91 if(strcmp("system", element_name)){
92 *error = g_error_new(G_MARKUP_ERROR,
93 G_LOG_LEVEL_WARNING,
94 "This is not system.xml file");
95 return;
96 }
97
98 while(attribute_names[i]){
99 if(strcmp("node_name", attribute_names[i])==0){
100 des->node_name = g_strdup(attribute_values[i]);
101 }else if(strcmp("domainname", attribute_names[i])==0){
102 des->domain_name = g_strdup(attribute_values[i]);
103 }else if(strcmp("cpu", attribute_names[i])==0){
104 des->nb_cpu = atoi(attribute_values[i]);
105 }else if(strcmp("arch_size", attribute_names[i])==0){
106 if(strcmp(attribute_values[i],"LP32") == 0) des->size = LTT_LP32;
107 else if(strcmp(attribute_values[i],"ILP32") == 0) des->size = LTT_ILP32;
108 else if(strcmp(attribute_values[i],"LP64") == 0) des->size = LTT_LP64;
109 else if(strcmp(attribute_values[i],"ILP64") == 0) des->size = LTT_ILP64;
110 else if(strcmp(attribute_values[i],"UNKNOWN") == 0) des->size = LTT_UNKNOWN;
111 }else if(strcmp("endian", attribute_names[i])==0){
112 if(strcmp(attribute_values[i],"LITTLE_ENDIAN") == 0)
113 des->endian = LTT_LITTLE_ENDIAN;
114 else if(strcmp(attribute_values[i],"BIG_ENDIAN") == 0)
115 des->endian = LTT_BIG_ENDIAN;
116 }else if(strcmp("kernel_name", attribute_names[i])==0){
117 des->kernel_name = g_strdup(attribute_values[i]);
118 }else if(strcmp("kernel_release", attribute_names[i])==0){
119 des->kernel_release = g_strdup(attribute_values[i]);
120 }else if(strcmp("kernel_version", attribute_names[i])==0){
121 des->kernel_version = g_strdup(attribute_values[i]);
122 }else if(strcmp("machine", attribute_names[i])==0){
123 des->machine = g_strdup(attribute_values[i]);
124 }else if(strcmp("processor", attribute_names[i])==0){
125 des->processor = g_strdup(attribute_values[i]);
126 }else if(strcmp("hardware_platform", attribute_names[i])==0){
127 des->hardware_platform = g_strdup(attribute_values[i]);
128 }else if(strcmp("operating_system", attribute_names[i])==0){
129 des->operating_system = g_strdup(attribute_values[i]);
130 }else if(strcmp("ltt_major_version", attribute_names[i])==0){
131 des->ltt_major_version = atoi(attribute_values[i]);
132 }else if(strcmp("ltt_minor_version", attribute_names[i])==0){
133 des->ltt_minor_version = atoi(attribute_values[i]);
134 }else if(strcmp("ltt_block_size", attribute_names[i])==0){
135 des->ltt_block_size = atoi(attribute_values[i]);
136 }else{
137 *error = g_error_new(G_MARKUP_ERROR,
138 G_LOG_LEVEL_WARNING,
139 "Not a valid attribute");
140 return;
141 }
142 i++;
143 }
144 }
145
146 static void parser_characters (GMarkupParseContext __UNUSED__ *context,
147 const gchar *text,
148 gsize __UNUSED__ text_len,
149 gpointer user_data,
150 GError __UNUSED__ **error)
151 {
152 LttSystemDescription* des = (LttSystemDescription* )user_data;
153 des->description = g_strdup(text);
154 }
155
156
157 /*****************************************************************************
158 *Function name
159 * ltt_tracefile_open : open a trace file, construct a LttTracefile
160 *Input params
161 * t : the trace containing the tracefile
162 * fileName : path name of the trace file
163 *Return value
164 * : a pointer to a tracefile
165 ****************************************************************************/
166
167 LttTracefile* ltt_tracefile_open(LttTrace * t, gchar * fileName)
168 {
169 LttTracefile * tf;
170 struct stat lTDFStat; /* Trace data file status */
171
172 tf = g_new(LttTracefile, 1);
173
174 //open the file
175 tf->name = g_strdup(fileName);
176 tf->trace = t;
177 tf->fd = g_open(fileName, O_RDONLY, 0);
178 if(tf->fd < 0){
179 g_warning("Unable to open input data file %s\n", fileName);
180 g_free(tf->name);
181 g_free(tf);
182 return NULL;
183 }
184
185 // Get the file's status
186 if(fstat(tf->fd, &lTDFStat) < 0){
187 g_warning("Unable to get the status of the input data file %s\n", fileName);
188 g_free(tf->name);
189 g_close(tf->fd);
190 g_free(tf);
191 return NULL;
192 }
193
194 // Is the file large enough to contain a trace
195 if(lTDFStat.st_size < (off_t)(sizeof(BlockStart) + EVENT_HEADER_SIZE)){
196 g_print("The input data file %s does not contain a trace\n", fileName);
197 g_free(tf->name);
198 g_close(tf->fd);
199 g_free(tf);
200 return NULL;
201 }
202
203 //store the size of the file
204 tf->file_size = lTDFStat.st_size;
205 tf->block_size = t->system_description->ltt_block_size;
206 tf->block_number = tf->file_size / tf->block_size;
207 tf->which_block = 0;
208
209 //allocate memory to contain the info of a block
210 tf->buffer = (void *) g_new(gchar, t->system_description->ltt_block_size);
211
212 //read the first block
213 if(readBlock(tf,1)) exit(1);
214
215 return tf;
216 }
217
218
219 /*****************************************************************************
220 *Open control and per cpu tracefiles
221 ****************************************************************************/
222
223 void ltt_tracefile_open_cpu(LttTrace *t, gchar * tracefile_name)
224 {
225 LttTracefile * tf;
226 tf = ltt_tracefile_open(t,tracefile_name);
227 if(!tf) return;
228 t->per_cpu_tracefile_number++;
229 g_ptr_array_add(t->per_cpu_tracefiles, tf);
230 }
231
232 gint ltt_tracefile_open_control(LttTrace *t, gchar * control_name)
233 {
234 LttTracefile * tf;
235 LttEvent ev;
236 LttFacility * f;
237 void * pos;
238 FacilityLoad fLoad;
239 unsigned int i;
240
241 tf = ltt_tracefile_open(t,control_name);
242 if(!tf) {
243 g_warning("ltt_tracefile_open_control : bad file descriptor");
244 return -1;
245 }
246 t->control_tracefile_number++;
247 g_ptr_array_add(t->control_tracefiles,tf);
248
249 //parse facilities tracefile to get base_id
250 if(strcmp(&control_name[strlen(control_name)-10],"facilities") ==0){
251 while(1){
252 if(!ltt_tracefile_read(tf,&ev)) return 0; // end of file
253
254 if(ev.event_id == TRACE_FACILITY_LOAD){
255 pos = ev.data;
256 fLoad.name = (gchar*)pos;
257 fLoad.checksum = *(LttChecksum*)(pos + strlen(fLoad.name));
258 fLoad.base_code = *(guint32 *)(pos + strlen(fLoad.name) + sizeof(LttChecksum));
259
260 for(i=0;i<t->facility_number;i++){
261 f = (LttFacility*)g_ptr_array_index(t->facilities,i);
262 if(strcmp(f->name,fLoad.name)==0 && fLoad.checksum==f->checksum){
263 f->base_id = fLoad.base_code;
264 break;
265 }
266 }
267 if(i==t->facility_number) {
268 g_warning("Facility: %s, checksum: %u is not found",
269 fLoad.name,(unsigned int)fLoad.checksum);
270 return -1;
271 }
272 }else if(ev.event_id == TRACE_BLOCK_START){
273 continue;
274 }else if(ev.event_id == TRACE_BLOCK_END){
275 break;
276 }else {
277 g_warning("Not valid facilities trace file");
278 return -1;
279 }
280 }
281 }
282 return 0;
283 }
284
285 /*****************************************************************************
286 *Function name
287 * ltt_tracefile_close: close a trace file,
288 *Input params
289 * t : tracefile which will be closed
290 ****************************************************************************/
291
292 void ltt_tracefile_close(LttTracefile *t)
293 {
294 g_free(t->name);
295 g_free(t->buffer);
296 close(t->fd);
297 g_free(t);
298 }
299
300
301 /*****************************************************************************
302 *Get system information
303 ****************************************************************************/
304 gint getSystemInfo(LttSystemDescription* des, gchar * pathname)
305 {
306 int fd;
307 GIOChannel *iochan;
308 gchar *buf = NULL;
309 gsize length;
310
311 GMarkupParseContext * context;
312 GError * error = NULL;
313 GMarkupParser markup_parser =
314 {
315 parser_start_element,
316 NULL,
317 parser_characters,
318 NULL, /* passthrough */
319 NULL /* error */
320 };
321
322 fd = g_open(pathname, O_RDONLY, 0);
323 if(fd == -1){
324 g_warning("Can not open file : %s\n", pathname);
325 return -1;
326 }
327
328 iochan = g_io_channel_unix_new(fd);
329
330 context = g_markup_parse_context_new(&markup_parser, 0, des,NULL);
331
332 //while(fgets(buf,DIR_NAME_SIZE, fp) != NULL){
333 while(g_io_channel_read_line(iochan, &buf, &length, NULL, &error)
334 != G_IO_STATUS_EOF) {
335
336 if(error != NULL) {
337 g_warning("Can not read xml file: \n%s\n", error->message);
338 g_error_free(error);
339 }
340 if(!g_markup_parse_context_parse(context, buf, length, &error)){
341 if(error != NULL) {
342 g_warning("Can not parse xml file: \n%s\n", error->message);
343 g_error_free(error);
344 }
345 g_markup_parse_context_free(context);
346
347 g_io_channel_shutdown(iochan, FALSE, &error); /* No flush */
348 if(error != NULL) {
349 g_warning("Can not close file: \n%s\n", error->message);
350 g_error_free(error);
351 }
352
353 close(fd);
354 return -1;
355 }
356 }
357 g_markup_parse_context_free(context);
358
359 g_io_channel_shutdown(iochan, FALSE, &error); /* No flush */
360 if(error != NULL) {
361 g_warning("Can not close file: \n%s\n", error->message);
362 g_error_free(error);
363 }
364
365 g_close(fd);
366
367 g_free(buf);
368 return 0;
369 }
370
371 /*****************************************************************************
372 *The following functions get facility/tracefile information
373 ****************************************************************************/
374
375 gint getFacilityInfo(LttTrace *t, gchar* eventdefs)
376 {
377 GDir * dir;
378 const gchar * name;
379 unsigned int i,j;
380 LttFacility * f;
381 LttEventType * et;
382 gchar fullname[DIR_NAME_SIZE];
383 GError * error = NULL;
384
385 dir = g_dir_open(eventdefs, 0, &error);
386
387 if(error != NULL) {
388 g_warning("Can not open directory: %s, %s\n", eventdefs, error->message);
389 g_error_free(error);
390 return -1;
391 }
392
393 while((name = g_dir_read_name(dir)) != NULL){
394 if(!g_pattern_match_simple("*.xml", name)) continue;
395 strcpy(fullname,eventdefs);
396 strcat(fullname,name);
397 ltt_facility_open(t,fullname);
398 }
399 g_dir_close(dir);
400
401 for(j=0;j<t->facility_number;j++){
402 f = (LttFacility*)g_ptr_array_index(t->facilities, j);
403 for(i=0; i<f->event_number; i++){
404 et = f->events[i];
405 setFieldsOffset(NULL, et, NULL, t);
406 }
407 }
408 return 0;
409 }
410
411 gint getControlFileInfo(LttTrace *t, gchar* control)
412 {
413 GDir * dir;
414 const gchar *name;
415 gchar fullname[DIR_NAME_SIZE];
416 GError * error = NULL;
417
418 dir = g_dir_open(control, 0, &error);
419
420 if(error != NULL) {
421 g_warning("Can not open directory: %s, %s\n", control, error->message);
422 g_error_free(error);
423 return -1;
424 }
425
426 while((name = g_dir_read_name(dir)) != NULL){
427 if(strcmp(name,"facilities") != 0 &&
428 strcmp(name,"interrupts") != 0 &&
429 strcmp(name,"processes") != 0) continue;
430
431 strcpy(fullname,control);
432 strcat(fullname,name);
433 if(ltt_tracefile_open_control(t,fullname)) {
434 g_dir_close(dir);
435 return -1;
436 }
437 }
438 g_dir_close(dir);
439 return 0;
440 }
441
442 gint getCpuFileInfo(LttTrace *t, char* cpu)
443 {
444 GDir * dir;
445 const gchar * name;
446 gchar fullname[DIR_NAME_SIZE];
447 GError * error = NULL;
448
449 dir = g_dir_open(cpu, 0, &error);
450
451 if(error != NULL) {
452 g_warning("Can not open directory: %s, %s\n", cpu, error->message);
453 g_error_free(error);
454 return -1;
455 }
456
457 while((name = g_dir_read_name(dir)) != NULL){
458 if(strcmp(name,".svn") != 0){ /* . and .. already excluded */
459 strcpy(fullname,cpu);
460 strcat(fullname,name);
461 ltt_tracefile_open_cpu(t,fullname);
462 }else continue;
463 }
464 g_dir_close(dir);
465 return 0;
466 }
467
468 /*****************************************************************************
469 *A trace is specified as a pathname to the directory containing all the
470 *associated data (control tracefiles, per cpu tracefiles, event
471 *descriptions...).
472 *
473 *When a trace is closed, all the associated facilities, types and fields
474 *are released as well.
475 */
476
477
478 /****************************************************************************
479 * get_absolute_pathname
480 *
481 * return the unique pathname in the system
482 *
483 * MD : Fixed this function so it uses realpath, dealing well with
484 * forgotten cases (.. were not used correctly before).
485 *
486 ****************************************************************************/
487 void get_absolute_pathname(const gchar *pathname, gchar * abs_pathname)
488 {
489 abs_pathname[0] = '\0';
490
491 if ( realpath (pathname, abs_pathname) != NULL)
492 return;
493 else
494 {
495 /* error, return the original path unmodified */
496 strcpy(abs_pathname, pathname);
497 return;
498 }
499 return;
500 }
501
502 LttTrace *ltt_trace_open(const gchar *pathname)
503 {
504 LttTrace * t;
505 LttSystemDescription * sys_description;
506 gchar eventdefs[DIR_NAME_SIZE];
507 gchar info[DIR_NAME_SIZE];
508 gchar control[DIR_NAME_SIZE];
509 gchar cpu[DIR_NAME_SIZE];
510 gchar tmp[DIR_NAME_SIZE];
511 gchar abs_path[DIR_NAME_SIZE];
512 gboolean has_slash = FALSE;
513
514 get_absolute_pathname(pathname, abs_path);
515 //establish the pathname to different directories
516 if(abs_path[strlen(abs_path)-1] == '/')has_slash = TRUE;
517 strcpy(eventdefs,abs_path);
518 if(!has_slash)strcat(eventdefs,"/");
519 strcat(eventdefs,"eventdefs/");
520
521 strcpy(info,abs_path);
522 if(!has_slash)strcat(info,"/");
523 strcat(info,"info/");
524
525 strcpy(control,abs_path);
526 if(!has_slash)strcat(control,"/");
527 strcat(control,"control/");
528
529 strcpy(cpu,abs_path);
530 if(!has_slash)strcat(cpu,"/");
531 strcat(cpu,"cpu/");
532
533 //new trace
534 sys_description = g_new(LttSystemDescription, 1);
535 t = g_new(LttTrace, 1);
536 t->pathname = g_strdup(abs_path);
537 t->facility_number = 0;
538 t->control_tracefile_number = 0;
539 t->per_cpu_tracefile_number = 0;
540 t->system_description = sys_description;
541 t->control_tracefiles = g_ptr_array_new();
542 t->per_cpu_tracefiles = g_ptr_array_new();
543 t->facilities = g_ptr_array_new();
544 //getDataEndianType(&(t->my_arch_size), &(t->my_arch_endian));
545
546 //get system description
547 strcpy(tmp,info);
548 strcat(tmp,"system.xml");
549 if(getSystemInfo(sys_description, tmp)) {
550 g_ptr_array_free(t->facilities, TRUE);
551 g_ptr_array_free(t->per_cpu_tracefiles, TRUE);
552 g_ptr_array_free(t->control_tracefiles, TRUE);
553 g_free(sys_description);
554 g_free(t->pathname);
555 g_free(t);
556 return NULL;
557 }
558
559 /* Set the reverse byte order between trace and reader */
560 if(sys_description->endian == LTT_LITTLE_ENDIAN
561 && G_BYTE_ORDER != G_LITTLE_ENDIAN) {
562 t->reverse_byte_order = 1;
563 } else if(sys_description->endian == LTT_BIG_ENDIAN
564 && G_BYTE_ORDER != G_BIG_ENDIAN) {
565 t->reverse_byte_order = 1;
566 } else t->reverse_byte_order = 0;
567
568 //get facilities info
569 if(getFacilityInfo(t,eventdefs)) {
570 g_ptr_array_free(t->facilities, TRUE);
571 g_ptr_array_free(t->per_cpu_tracefiles, TRUE);
572 g_ptr_array_free(t->control_tracefiles, TRUE);
573 g_free(sys_description);
574 g_free(t->pathname);
575 g_free(t);
576 return NULL;
577 }
578
579 //get control tracefile info
580 getControlFileInfo(t,control);
581 /*
582 if(getControlFileInfo(t,control)) {
583 g_ptr_array_free(t->facilities, TRUE);
584 g_ptr_array_free(t->per_cpu_tracefiles, TRUE);
585 g_ptr_array_free(t->control_tracefiles, TRUE);
586 g_free(sys_description);
587 g_free(t->pathname);
588 g_free(t);
589 return NULL;
590 }*/ // With fatal error
591
592 //get cpu tracefile info
593 if(getCpuFileInfo(t,cpu)) {
594 g_ptr_array_free(t->facilities, TRUE);
595 g_ptr_array_free(t->per_cpu_tracefiles, TRUE);
596 g_ptr_array_free(t->control_tracefiles, TRUE);
597 g_free(sys_description);
598 g_free(t->pathname);
599 g_free(t);
600 return NULL;
601 }
602
603 return t;
604 }
605
606 char * ltt_trace_name(LttTrace *t)
607 {
608 return t->pathname;
609 }
610
611
612 /******************************************************************************
613 * When we copy a trace, we want all the opening actions to happen again :
614 * the trace will be reopened and totally independant from the original.
615 * That's why we call ltt_trace_open.
616 *****************************************************************************/
617 LttTrace *ltt_trace_copy(LttTrace *self)
618 {
619 return ltt_trace_open(self->pathname);
620 }
621
622 void ltt_trace_close(LttTrace *t)
623 {
624 unsigned int i;
625 LttTracefile * tf;
626 LttFacility * f;
627
628 g_free(t->pathname);
629
630 //free system_description
631 g_free(t->system_description->description);
632 g_free(t->system_description->node_name);
633 g_free(t->system_description->domain_name);
634 g_free(t->system_description->kernel_name);
635 g_free(t->system_description->kernel_release);
636 g_free(t->system_description->kernel_version);
637 g_free(t->system_description->machine);
638 g_free(t->system_description->processor);
639 g_free(t->system_description->hardware_platform);
640 g_free(t->system_description->operating_system);
641 g_free(t->system_description);
642
643 //free control_tracefiles
644 for(i=0;i<t->control_tracefile_number;i++){
645 tf = (LttTracefile*)g_ptr_array_index(t->control_tracefiles,i);
646 ltt_tracefile_close(tf);
647 }
648 g_ptr_array_free(t->control_tracefiles, TRUE);
649
650 //free per_cpu_tracefiles
651 for(i=0;i<t->per_cpu_tracefile_number;i++){
652 tf = (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles,i);
653 ltt_tracefile_close(tf);
654 }
655 g_ptr_array_free(t->per_cpu_tracefiles, TRUE);
656
657 //free facilities
658 for(i=0;i<t->facility_number;i++){
659 f = (LttFacility*)g_ptr_array_index(t->facilities,i);
660 ltt_facility_close(f);
661 }
662 g_ptr_array_free(t->facilities, TRUE);
663
664 g_free(t);
665
666 g_blow_chunks();
667 }
668
669
670 /*****************************************************************************
671 *Get the system description of the trace
672 ****************************************************************************/
673
674 LttSystemDescription *ltt_trace_system_description(LttTrace *t)
675 {
676 return t->system_description;
677 }
678
679 /*****************************************************************************
680 * The following functions discover the facilities of the trace
681 ****************************************************************************/
682
683 unsigned ltt_trace_facility_number(LttTrace *t)
684 {
685 return (unsigned)(t->facility_number);
686 }
687
688 LttFacility *ltt_trace_facility_get(LttTrace *t, unsigned i)
689 {
690 return (LttFacility*)g_ptr_array_index(t->facilities, i);
691 }
692
693 /*****************************************************************************
694 *Function name
695 * ltt_trace_facility_find : find facilities in the trace
696 *Input params
697 * t : the trace
698 * name : facility name
699 *Output params
700 * position : position of the facility in the trace
701 *Return value
702 * : the number of facilities
703 ****************************************************************************/
704
705 unsigned ltt_trace_facility_find(LttTrace *t, char *name, unsigned *position)
706 {
707 unsigned int i, count=0;
708 LttFacility * f;
709 for(i=0;i<t->facility_number;i++){
710 f = (LttFacility*)g_ptr_array_index(t->facilities, i);
711 if(strcmp(f->name,name)==0){
712 count++;
713 if(count==1) *position = i;
714 }else{
715 if(count) break;
716 }
717 }
718 return count;
719 }
720
721 /*****************************************************************************
722 * Functions to discover all the event types in the trace
723 ****************************************************************************/
724
725 unsigned ltt_trace_eventtype_number(LttTrace *t)
726 {
727 unsigned int i;
728 unsigned count = 0;
729 unsigned int num = t->facility_number;
730 LttFacility * f;
731
732 for(i=0;i<num;i++){
733 f = (LttFacility*)g_ptr_array_index(t->facilities, i);
734 count += f->event_number;
735 }
736 return count;
737 }
738
739 /* FIXME : performances could be improved with a better design for this
740 * function : sequential search through a container has never been the
741 * best on the critical path. */
742 LttFacility * ltt_trace_facility_by_id(LttTrace * trace, unsigned id)
743 {
744 LttFacility * facility = NULL;
745 unsigned int i;
746 unsigned int num = trace->facility_number;
747 GPtrArray *facilities = trace->facilities;
748
749 for(i=0;unlikely(i<num);){
750 LttFacility *iter_facility =
751 (LttFacility*) g_ptr_array_index(facilities,i);
752 unsigned base_id = iter_facility->base_id;
753
754 if(likely(id >= base_id &&
755 id < base_id + iter_facility->event_number)) {
756 facility = iter_facility;
757 break;
758 } else {
759 i++;
760 }
761 }
762
763 return facility;
764 }
765
766 LttEventType *ltt_trace_eventtype_get(LttTrace *t, unsigned evId)
767 {
768 LttEventType *event_type;
769
770 LttFacility * f;
771 f = ltt_trace_facility_by_id(t,evId);
772
773 if(unlikely(!f)) event_type = NULL;
774 else event_type = f->events[evId - f->base_id];
775
776 return event_type;
777 }
778
779 /*****************************************************************************
780 *There is one "per cpu" tracefile for each CPU, numbered from 0 to
781 *the maximum number of CPU in the system. When the number of CPU installed
782 *is less than the maximum, some positions are unused. There are also a
783 *number of "control" tracefiles (facilities, interrupts...).
784 ****************************************************************************/
785 unsigned ltt_trace_control_tracefile_number(LttTrace *t)
786 {
787 return t->control_tracefile_number;
788 }
789
790 unsigned ltt_trace_per_cpu_tracefile_number(LttTrace *t)
791 {
792 return t->per_cpu_tracefile_number;
793 }
794
795 /*****************************************************************************
796 *It is possible to search for the tracefiles by name or by CPU position.
797 *The index within the tracefiles of the same type is returned if found
798 *and a negative value otherwise.
799 ****************************************************************************/
800
801 int ltt_trace_control_tracefile_find(LttTrace *t, const gchar *name)
802 {
803 LttTracefile * tracefile;
804 unsigned int i;
805 for(i=0;i<t->control_tracefile_number;i++){
806 tracefile = (LttTracefile*)g_ptr_array_index(t->control_tracefiles, i);
807 if(strcmp(tracefile->name, name)==0)break;
808 }
809 if(i == t->control_tracefile_number) return -1;
810 return i;
811 }
812
813 /* not really useful. We just have to know that cpu tracefiles
814 * comes before control tracefiles.
815 */
816 int ltt_trace_per_cpu_tracefile_find(LttTrace *t, const gchar *name)
817 {
818 LttTracefile * tracefile;
819 unsigned int i;
820 for(i=0;i<t->per_cpu_tracefile_number;i++){
821 tracefile = (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles, i);
822 if(strcmp(tracefile->name, name)==0)break;
823 }
824 if(i == t->per_cpu_tracefile_number) return -1;
825 return i;
826 }
827
828 /*****************************************************************************
829 *Get a specific tracefile
830 ****************************************************************************/
831
832 LttTracefile *ltt_trace_control_tracefile_get(LttTrace *t, unsigned i)
833 {
834 return (LttTracefile*)g_ptr_array_index(t->control_tracefiles, i);
835 }
836
837 LttTracefile *ltt_trace_per_cpu_tracefile_get(LttTrace *t, unsigned i)
838 {
839 return (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles, i);
840 }
841
842 /*****************************************************************************
843 * Get the start time and end time of the trace
844 ****************************************************************************/
845
846 void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end)
847 {
848 LttTime startSmall, startTmp, endBig, endTmp;
849 unsigned int i, j=0;
850 LttTracefile * tf;
851
852 for(i=0;i<t->control_tracefile_number;i++){
853 tf = g_ptr_array_index(t->control_tracefiles, i);
854 readBlock(tf,1);
855 startTmp = ltt_get_time(t->reverse_byte_order, &tf->a_block_start->time);
856 readBlock(tf,tf->block_number);
857 endTmp = ltt_get_time(t->reverse_byte_order, &tf->a_block_end->time);
858 if(i==0){
859 startSmall = startTmp;
860 endBig = endTmp;
861 j = 1;
862 continue;
863 }
864 if(ltt_time_compare(startSmall,startTmp) > 0) startSmall = startTmp;
865 if(ltt_time_compare(endBig,endTmp) < 0) endBig = endTmp;
866 }
867
868 for(i=0;i<t->per_cpu_tracefile_number;i++){
869 tf = g_ptr_array_index(t->per_cpu_tracefiles, i);
870 readBlock(tf,1);
871 startTmp = ltt_get_time(t->reverse_byte_order, &tf->a_block_start->time);
872 readBlock(tf,tf->block_number);
873 endTmp = ltt_get_time(t->reverse_byte_order, &tf->a_block_end->time);
874 if(j == 0 && i==0){
875 startSmall = startTmp;
876 endBig = endTmp;
877 continue;
878 }
879 if(ltt_time_compare(startSmall,startTmp) > 0) startSmall = startTmp;
880 if(ltt_time_compare(endBig,endTmp) < 0) endBig = endTmp;
881 }
882
883 if(start != NULL) *start = startSmall;
884 if(end != NULL) *end = endBig;
885 }
886
887
888 /*****************************************************************************
889 *Get the name of a tracefile
890 ****************************************************************************/
891
892 char *ltt_tracefile_name(LttTracefile *tf)
893 {
894 return tf->name;
895 }
896
897 /*****************************************************************************
898 * Get the number of blocks in the tracefile
899 ****************************************************************************/
900
901 unsigned ltt_tracefile_block_number(LttTracefile *tf)
902 {
903 return tf->block_number;
904 }
905
906 /*****************************************************************************
907 *Function name
908 * ltt_tracefile_seek_time: seek to the first event of the trace with time
909 * larger or equal to time
910 *Input params
911 * t : tracefile
912 * time : criteria of the time
913 ****************************************************************************/
914 void ltt_tracefile_find_time_block(LttTracefile *t, LttTime time,
915 int start_block, int end_block)
916 {
917 int err, tmp_block, s, e;
918 int headTime;
919 int tailTime;
920
921 err=readBlock(t,start_block);
922 if(err) g_error("Can not read tracefile: %s\n", t->name);
923 if(start_block == end_block)return;
924
925 tailTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order,
926 &t->a_block_end->time), time);
927 if(tailTime >= 0) return;
928
929 err=readBlock(t,end_block);
930 if(err) g_error("Can not read tracefile: %s\n", t->name);
931 if(start_block+1 == end_block)return;
932
933 headTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order,
934 &t->a_block_start->time), time);
935 if(headTime <= 0 ) return;
936
937 tmp_block = (end_block + start_block)/2;
938 err=readBlock(t,tmp_block);
939 if(err) g_error("Can not read tracefile: %s\n", t->name);
940
941 headTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order,
942 &t->a_block_start->time), time);
943 tailTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order,
944 &t->a_block_end->time), time);
945 if(headTime <= 0 && tailTime >= 0) return;
946
947 if(headTime > 0){
948 s = start_block + 1;
949 e = tmp_block - 1;
950 if(s <= e)
951 ltt_tracefile_find_time_block(t, time, s, e);
952 else return;
953 }
954
955 if(tailTime < 0){
956 s = tmp_block + 1;
957 e = end_block - 1;
958 if(s <= e)
959 ltt_tracefile_find_time_block(t, time, s, e);
960 else return;
961 }
962 }
963
964 void ltt_tracefile_backward_find_time_block(LttTracefile *t, LttTime time)
965 {
966 int t_time, h_time, err;
967 err=readBlock(t,t->which_block-1);
968 if(err) g_error("Can not read tracefile: %s\n", t->name);
969 h_time = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order,
970 &t->a_block_start->time), time);
971 t_time = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order,
972 &t->a_block_end->time), time);
973 if(h_time == 0){
974 int tmp;
975 if(t->which_block == 1) return;
976 err=readBlock(t,t->which_block-1);
977 if(err) g_error("Can not read tracefile: %s\n", t->name);
978 tmp = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order,
979 &t->a_block_end->time), time);
980 if(tmp == 0) return ltt_tracefile_seek_time(t, time);
981 err=readBlock(t,t->which_block+1);
982 if(err) g_error("Can not read tracefile: %s\n", t->name);
983 }else if(h_time > 0){
984 ltt_tracefile_find_time_block(t, time, 1, t->which_block);
985 return ltt_tracefile_seek_time(t, time) ;
986 }else{
987 if(t_time >= 0) return ltt_tracefile_seek_time(t, time);
988 err=readBlock(t,t->which_block+1);
989 if(err) g_error("Can not read tracefile: %s\n", t->name);
990 }
991 }
992
993 void ltt_tracefile_seek_time(LttTracefile *t, LttTime time)
994 {
995 int err;
996 LttTime lttTime;
997 int headTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order,
998 &t->a_block_start->time), time);
999 int tailTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order,
1000 &t->a_block_end->time), time);
1001 LttEvent ev;
1002
1003 if(headTime < 0 && tailTime > 0){
1004 if(ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order,
1005 &t->a_block_end->time),
1006 t->current_event_time) !=0) {
1007 lttTime = getEventTime(t);
1008 err = ltt_time_compare(lttTime, time);
1009 if(err > 0){
1010 if(t->which_event==2 || ltt_time_compare(t->prev_event_time,time)<0){
1011 return;
1012 }else{
1013 updateTracefile(t);
1014 return ltt_tracefile_seek_time(t, time);
1015 }
1016 }else if(err < 0){
1017 while(1){
1018 if(ltt_tracefile_read(t,&ev) == NULL) {
1019 g_print("End of file\n");
1020 return;
1021 }
1022 lttTime = getEventTime(t);
1023 err = ltt_time_compare(lttTime, time);
1024 if(err >= 0)return;
1025 }
1026 }else return;
1027 }else{//we are at the end of the block
1028 updateTracefile(t);
1029 return ltt_tracefile_seek_time(t, time);
1030 }
1031 }else if(headTime >= 0){
1032 if(t->which_block == 1){
1033 updateTracefile(t);
1034 }else{
1035 if(ltt_time_compare(t->prev_block_end_time, time) >= 0 ||
1036 (t->prev_block_end_time.tv_sec == 0 &&
1037 t->prev_block_end_time.tv_nsec == 0 )){
1038 ltt_tracefile_backward_find_time_block(t, time);
1039 }else{
1040 updateTracefile(t);
1041 }
1042 }
1043 }else if(tailTime < 0){
1044 if(t->which_block != t->block_number){
1045 ltt_tracefile_find_time_block(t, time, t->which_block+1, t->block_number);
1046 return ltt_tracefile_seek_time(t, time);
1047 }else {
1048 t->cur_event_pos = t->buffer + t->block_size;
1049 g_print("End of file\n");
1050 return;
1051 }
1052 }else if(tailTime == 0){
1053 t->cur_event_pos = t->last_event_pos;
1054 t->current_event_time = time;
1055 t->cur_heart_beat_number = 0;
1056 t->prev_event_time.tv_sec = 0;
1057 t->prev_event_time.tv_nsec = 0;
1058 return;
1059 }
1060 }
1061
1062 /*****************************************************************************
1063 * Seek to the first event with position equal or larger to ep
1064 *
1065 * Modified by Mathieu Desnoyers to used faster offset position instead of
1066 * re-reading the whole buffer.
1067 ****************************************************************************/
1068
1069 void ltt_tracefile_seek_position(LttTracefile *t, const LttEventPosition *ep)
1070 {
1071 //if we are at the right place, just return
1072 if(likely(t->which_block == ep->block_num && t->which_event == ep->event_num))
1073 return;
1074
1075 if(likely(t->which_block == ep->block_num)) updateTracefile(t);
1076 else readBlock(t,ep->block_num);
1077 //event offset is available
1078 if(likely(ep->old_position)){
1079 int err;
1080
1081 t->which_event = ep->event_num;
1082 t->cur_event_pos = t->buffer + ep->event_offset;
1083 t->prev_event_time = ep->event_time;
1084 t->current_event_time = ep->event_time;
1085 t->cur_heart_beat_number = ep->heart_beat_number;
1086 t->cur_cycle_count = ep->event_cycle_count;
1087
1088 /* This is a workaround for fast position seek */
1089 t->last_event_pos = ep->last_event_pos;
1090 t->prev_block_end_time = ep->prev_block_end_time;
1091 t->prev_event_time = ep->prev_event_time;
1092 t->pre_cycle_count = ep->pre_cycle_count;
1093 t->count = ep->count;
1094 t->overflow_nsec = ep->overflow_nsec;
1095 t->last_heartbeat = ep->last_heartbeat;
1096 /* end of workaround */
1097
1098 //update the fields of the current event and go to the next event
1099 err = skipEvent(t);
1100 if(unlikely(err == ERANGE)) g_error("event id is out of range\n");
1101
1102 return;
1103 }
1104
1105 //only block number and event index are available
1106 //MD: warning : this is slow!
1107 g_warning("using slow O(n) tracefile seek position");
1108
1109 LttEvent event;
1110 while(likely(t->which_event < ep->event_num)) ltt_tracefile_read(t, &event);
1111
1112 return;
1113 }
1114
1115 /*****************************************************************************
1116 *Function name
1117 * ltt_tracefile_read : read the current event, set the pointer to the next
1118 *Input params
1119 * t : tracefile
1120 *Return value
1121 * LttEvent * : an event to be processed
1122 ****************************************************************************/
1123
1124 LttEvent *ltt_tracefile_read(LttTracefile *t, LttEvent *event)
1125 {
1126 int err;
1127
1128 if(unlikely(t->cur_event_pos == t->buffer + t->block_size)){
1129 if(unlikely(t->which_block == t->block_number)){
1130 return NULL;
1131 }
1132 err = readBlock(t, t->which_block + 1);
1133 if(unlikely(err))g_error("Can not read tracefile");
1134 }
1135
1136 event->event_id = ltt_get_uint16(t->trace->reverse_byte_order, t->cur_event_pos);
1137 if(unlikely(event->event_id == TRACE_TIME_HEARTBEAT))
1138 t->cur_heart_beat_number++;
1139
1140 t->prev_event_time = t->current_event_time;
1141 // t->current_event_time = getEventTime(t);
1142
1143 event->time_delta = ltt_get_uint32(t->trace->reverse_byte_order, t->cur_event_pos + EVENT_ID_SIZE);
1144 event->event_time = t->current_event_time;
1145 event->event_cycle_count = t->cur_cycle_count;
1146
1147 event->tracefile = t;
1148 event->data = t->cur_event_pos + EVENT_HEADER_SIZE;
1149 event->which_block = t->which_block;
1150 event->which_event = t->which_event;
1151
1152 /* This is a workaround for fast position seek */
1153 event->last_event_pos = t->last_event_pos;
1154 event->prev_block_end_time = t->prev_block_end_time;
1155 event->prev_event_time = t->prev_event_time;
1156 event->pre_cycle_count = t->pre_cycle_count;
1157 event->count = t->count;
1158 event->overflow_nsec = t->overflow_nsec;
1159 event->last_heartbeat = t->last_heartbeat;
1160
1161 /* end of workaround */
1162
1163
1164
1165 //update the fields of the current event and go to the next event
1166 err = skipEvent(t);
1167 if(unlikely(err == ERANGE)) g_error("event id is out of range\n");
1168
1169 return event;
1170 }
1171
1172 /****************************************************************************
1173 *Function name
1174 * readFile : wrap function to read from a file
1175 *Input Params
1176 * fd : file descriptor
1177 * buf : buf to contain the content
1178 * size : number of bytes to be read
1179 * mesg : message to be printed if some thing goes wrong
1180 *return value
1181 * 0 : success
1182 * EIO : can not read from the file
1183 ****************************************************************************/
1184
1185 int readFile(int fd, void * buf, size_t size, char * mesg)
1186 {
1187 ssize_t nbBytes = read(fd, buf, size);
1188
1189 if((size_t)nbBytes != size) {
1190 if(nbBytes < 0) {
1191 perror("Error in readFile : ");
1192 } else {
1193 g_warning("%s",mesg);
1194 }
1195 return EIO;
1196 }
1197 return 0;
1198 }
1199
1200
1201 /****************************************************************************
1202 *Function name
1203 * readBlock : read a block from the file
1204 *Input Params
1205 * lttdes : ltt trace file
1206 * whichBlock : the block which will be read
1207 *return value
1208 * 0 : success
1209 * EINVAL : lseek fail
1210 * EIO : can not read from the file
1211 ****************************************************************************/
1212
1213 int readBlock(LttTracefile * tf, int whichBlock)
1214 {
1215 off_t nbBytes;
1216 guint32 lostSize;
1217
1218 /* same block already opened requested */
1219 if((guint)whichBlock == tf->which_block) return 0;
1220
1221 if(likely(whichBlock - tf->which_block == 1 && tf->which_block != 0)){
1222 tf->prev_block_end_time = ltt_get_time(tf->trace->reverse_byte_order,
1223 &tf->a_block_end->time);
1224 tf->prev_event_time = ltt_get_time(tf->trace->reverse_byte_order,
1225 &tf->a_block_end->time);
1226 }else{
1227 tf->prev_block_end_time.tv_sec = 0;
1228 tf->prev_block_end_time.tv_nsec = 0;
1229 tf->prev_event_time.tv_sec = 0;
1230 tf->prev_event_time.tv_nsec = 0;
1231 }
1232
1233 nbBytes=lseek(tf->fd,(off_t)((whichBlock-1)*tf->block_size), SEEK_SET);
1234 if(unlikely(nbBytes == -1)) return EINVAL;
1235
1236 if(unlikely(readFile(tf->fd,tf->buffer,tf->block_size,"Unable to read a block")))
1237 return EIO;
1238
1239 tf->a_block_start=(BlockStart *) (tf->buffer + EVENT_HEADER_SIZE);
1240 lostSize = *(guint32 *)(tf->buffer + tf->block_size - sizeof(guint32));
1241 tf->a_block_end=(BlockEnd *)(tf->buffer + tf->block_size
1242 - sizeof(guint32) - lostSize - sizeof(BlockEnd));
1243 tf->last_event_pos = tf->buffer + tf->block_size -
1244 sizeof(guint32) - lostSize
1245 - sizeof(BlockEnd) - EVENT_HEADER_SIZE;
1246
1247 tf->which_block = whichBlock;
1248 tf->which_event = 1;
1249 tf->cur_event_pos = tf->buffer;//the beginning of the block, block start ev
1250 tf->cur_heart_beat_number = 0;
1251 tf->last_heartbeat = NULL;
1252
1253 /* read the whole block to precalculate total of cycles in it */
1254 tf->count = 0;
1255 tf->pre_cycle_count = 0;
1256 tf->cur_cycle_count = ltt_get_uint32(tf->trace->reverse_byte_order, tf->cur_event_pos + EVENT_ID_SIZE);
1257
1258 getCyclePerNsec(tf);
1259
1260 tf->overflow_nsec =
1261 (-((double)
1262 (ltt_get_uint64(tf->trace->reverse_byte_order,
1263 &tf->a_block_start->cycle_count)&0xFFFFFFFF))
1264 * tf->nsec_per_cycle);
1265
1266 tf->current_event_time = getEventTime(tf);
1267
1268 return 0;
1269 }
1270
1271 /*****************************************************************************
1272 *Function name
1273 * updateTracefile : reinitialize the info of the block which is already
1274 * in the buffer
1275 *Input params
1276 * tf : tracefile
1277 ****************************************************************************/
1278
1279 void updateTracefile(LttTracefile * tf)
1280 {
1281 tf->which_event = 1;
1282 tf->cur_event_pos = tf->buffer;
1283 tf->current_event_time = getEventTime(tf);
1284 tf->cur_heart_beat_number = 0;
1285
1286 tf->prev_event_time.tv_sec = 0;
1287 tf->prev_event_time.tv_nsec = 0;
1288 tf->count = 0;
1289
1290 tf->overflow_nsec =
1291 (-((double)ltt_get_uint64(tf->trace->reverse_byte_order,
1292 &tf->a_block_start->cycle_count))
1293 * tf->nsec_per_cycle);
1294
1295 }
1296
1297 /*****************************************************************************
1298 *Function name
1299 * skipEvent : go to the next event, update the fields of the current event
1300 *Input params
1301 * t : tracefile
1302 *return value
1303 * 0 : success
1304 * ERANGE : event id is out of range
1305 ****************************************************************************/
1306
1307 int skipEvent(LttTracefile * t)
1308 {
1309 int evId;
1310 void * evData;
1311 LttEventType * evT;
1312 LttField * rootFld;
1313
1314 evId = ltt_get_uint16(t->trace->reverse_byte_order, t->cur_event_pos);
1315 evData = t->cur_event_pos + EVENT_HEADER_SIZE;
1316
1317 evT = ltt_trace_eventtype_get(t->trace,(unsigned)evId);
1318
1319 if(likely(evT)) rootFld = evT->root_field;
1320 else return ERANGE;
1321
1322 if(likely(rootFld)){
1323 //event has string/sequence or the last event is not the same event
1324 if(likely((evT->latest_block!=t->which_block || evT->latest_event!=t->which_event)
1325 && rootFld->field_fixed == 0)){
1326 setFieldsOffset(t, evT, evData, t->trace);
1327 }
1328 t->cur_event_pos += EVENT_HEADER_SIZE + rootFld->field_size;
1329 }else t->cur_event_pos += EVENT_HEADER_SIZE;
1330
1331 evT->latest_block = t->which_block;
1332 evT->latest_event = t->which_event;
1333
1334 //the next event is in the next block
1335 if(unlikely(evId == TRACE_BLOCK_END)){
1336 t->cur_event_pos = t->buffer + t->block_size;
1337 }else{
1338 t->cur_cycle_count = ltt_get_uint32(t->trace->reverse_byte_order,
1339 t->cur_event_pos + EVENT_ID_SIZE);
1340 t->which_event++;
1341 t->current_event_time = getEventTime(t);
1342 }
1343
1344 return 0;
1345 }
1346
1347
1348 /*****************************************************************************
1349 *Function name
1350 * getCyclePerNsec : calculate cycles per nsec for current block
1351 * MD: should have tracefile_read the whole block, so we know the
1352 * total of cycles in it before being called.
1353 *Input Params
1354 * t : tracefile
1355 ****************************************************************************/
1356
1357 void getCyclePerNsec(LttTracefile * t)
1358 {
1359 LttTime lBufTotalTime; /* Total time for this buffer */
1360 double lBufTotalNSec; /* Total time for this buffer in nsecs */
1361 LttCycleCount lBufTotalCycle;/* Total cycles for this buffer */
1362
1363 /* Calculate the total time for this buffer */
1364 lBufTotalTime = ltt_time_sub(
1365 ltt_get_time(t->trace->reverse_byte_order, &t->a_block_end->time),
1366 ltt_get_time(t->trace->reverse_byte_order, &t->a_block_start->time));
1367
1368 /* Calculate the total cycles for this bufffer */
1369 lBufTotalCycle = ltt_get_uint64(t->trace->reverse_byte_order,
1370 &t->a_block_end->cycle_count);
1371 lBufTotalCycle -= ltt_get_uint64(t->trace->reverse_byte_order,
1372 &t->a_block_start->cycle_count);
1373
1374 /* Convert the total time to double */
1375 lBufTotalNSec = ltt_time_to_double(lBufTotalTime);
1376
1377 t->nsec_per_cycle = (double)lBufTotalNSec / (double)lBufTotalCycle;
1378
1379 /* Pre-multiply one overflow (2^32 cycles) by nsec_per_cycle */
1380 t->one_overflow_nsec = t->nsec_per_cycle * (double)0x100000000ULL;
1381
1382 }
1383
1384 /****************************************************************************
1385 *Function name
1386 * getEventTime : obtain the time of an event
1387 * NOTE : this function _really_ is on critical path.
1388 *Input params
1389 * tf : tracefile
1390 *Return value
1391 * LttTime : the time of the event
1392 ****************************************************************************/
1393
1394 static inline LttTime getEventTime(LttTracefile * tf)
1395 {
1396 LttTime time;
1397 LttCycleCount cycle_count; // cycle count for the current event
1398 //LttCycleCount lEventTotalCycle; // Total cycles from start for event
1399 gint64 lEventNSec; // Total nsecs from start for event
1400 LttTime lTimeOffset; // Time offset in struct LttTime
1401 guint16 evId;
1402
1403 evId = ltt_get_uint16(tf->trace->reverse_byte_order,
1404 tf->cur_event_pos);
1405
1406 cycle_count = ltt_get_uint32(tf->trace->reverse_byte_order,
1407 tf->cur_event_pos + EVENT_ID_SIZE);
1408
1409 gboolean comp_count = cycle_count < tf->pre_cycle_count;
1410
1411 tf->pre_cycle_count = cycle_count;
1412
1413 if(unlikely(comp_count)) {
1414 /* Overflow */
1415 tf->overflow_nsec += tf->one_overflow_nsec;
1416 tf->count++; //increment overflow count
1417 }
1418
1419 if(unlikely(evId == TRACE_BLOCK_START)) {
1420 lEventNSec = 0;
1421 } else if(unlikely(evId == TRACE_BLOCK_END)) {
1422 lEventNSec = ((double)
1423 (ltt_get_uint64(tf->trace->reverse_byte_order,
1424 &tf->a_block_end->cycle_count)
1425 - ltt_get_uint64(tf->trace->reverse_byte_order,
1426 &tf->a_block_start->cycle_count))
1427 * tf->nsec_per_cycle);
1428 }
1429 #if 0
1430 /* If you want to make heart beat a special case and use their own 64 bits
1431 * TSC, activate this.
1432 */
1433 else if(unlikely(evId == TRACE_TIME_HEARTBEAT)) {
1434
1435 tf->last_heartbeat = (TimeHeartbeat*)(tf->cur_event_pos+EVENT_HEADER_SIZE);
1436 lEventNSec = ((double)(tf->last_heartbeat->cycle_count
1437 - tf->a_block_start->cycle_count)
1438 * tf->nsec_per_cycle);
1439 }
1440 #endif //0
1441 else {
1442 lEventNSec = (gint64)((double)cycle_count * tf->nsec_per_cycle)
1443 +tf->overflow_nsec;
1444 }
1445
1446 lTimeOffset = ltt_time_from_uint64(lEventNSec);
1447
1448 time = ltt_time_add(ltt_get_time(tf->trace->reverse_byte_order,
1449 &tf->a_block_start->time), lTimeOffset);
1450
1451 return time;
1452 }
1453
1454 /*****************************************************************************
1455 *Function name
1456 * setFieldsOffset : set offset of the fields
1457 *Input params
1458 * tracefile : opened trace file
1459 * evT : the event type
1460 * evD : event data, it may be NULL
1461 ****************************************************************************/
1462
1463 void setFieldsOffset(LttTracefile *tf,LttEventType *evT,void *evD,LttTrace* t)
1464 {
1465 LttField * rootFld = evT->root_field;
1466 // rootFld->base_address = evD;
1467
1468 if(likely(rootFld))
1469 rootFld->field_size = getFieldtypeSize(tf, evT, 0,0,rootFld, evD,t);
1470 }
1471
1472 /*****************************************************************************
1473 *Function name
1474 * getFieldtypeSize: get the size of the field type (primitive type)
1475 *Input params
1476 * tracefile : opened trace file
1477 * evT : event type
1478 * offsetRoot : offset from the root
1479 * offsetParent : offset from the parrent
1480 * fld : field
1481 * evD : event data, it may be NULL
1482 *Return value
1483 * int : size of the field
1484 ****************************************************************************/
1485
1486 static inline gint getFieldtypeSize(LttTracefile * t,
1487 LttEventType * evT, gint offsetRoot,
1488 gint offsetParent, LttField * fld, void *evD, LttTrace *trace)
1489 {
1490 gint size, size1, element_number, i, offset1, offset2;
1491 LttType * type = fld->field_type;
1492
1493 if(unlikely(t && evT->latest_block==t->which_block &&
1494 evT->latest_event==t->which_event)){
1495 size = fld->field_size;
1496 goto end_getFieldtypeSize;
1497 } else {
1498 /* This likely has been tested with gcov : half of them.. */
1499 if(unlikely(fld->field_fixed == 1)){
1500 /* tested : none */
1501 if(unlikely(fld == evT->root_field)) {
1502 size = fld->field_size;
1503 goto end_getFieldtypeSize;
1504 }
1505 }
1506
1507 /* From gcov profiling : half string, half struct, can we gain something
1508 * from that ? (Mathieu) */
1509 switch(type->type_class) {
1510 case LTT_ARRAY:
1511 element_number = (int) type->element_number;
1512 if(fld->field_fixed == -1){
1513 size = getFieldtypeSize(t, evT, offsetRoot,
1514 0,fld->child[0], NULL, trace);
1515 if(size == 0){ //has string or sequence
1516 fld->field_fixed = 0;
1517 }else{
1518 fld->field_fixed = 1;
1519 size *= element_number;
1520 }
1521 }else if(fld->field_fixed == 0){// has string or sequence
1522 size = 0;
1523 for(i=0;i<element_number;i++){
1524 size += getFieldtypeSize(t, evT, offsetRoot+size,size,
1525 fld->child[0], evD+size, trace);
1526 }
1527 }else size = fld->field_size;
1528 if(unlikely(!evD)){
1529 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
1530 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
1531 }
1532
1533 break;
1534
1535 case LTT_SEQUENCE:
1536 size1 = (int) ltt_type_size(trace, type);
1537 if(fld->field_fixed == -1){
1538 fld->sequ_number_size = size1;
1539 fld->field_fixed = 0;
1540 size = getFieldtypeSize(t, evT, offsetRoot,
1541 0,fld->child[0], NULL, trace);
1542 fld->element_size = size;
1543 }else{//0: sequence
1544 element_number = getIntNumber(t->trace->reverse_byte_order,size1,evD);
1545 type->element_number = element_number;
1546 if(fld->element_size > 0){
1547 size = element_number * fld->element_size;
1548 }else{//sequence has string or sequence
1549 size = 0;
1550 for(i=0;i<element_number;i++){
1551 size += getFieldtypeSize(t, evT, offsetRoot+size+size1,size+size1,
1552 fld->child[0], evD+size+size1, trace);
1553 }
1554 }
1555 size += size1;
1556 }
1557 if(unlikely(!evD)){
1558 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
1559 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
1560 }
1561
1562 break;
1563
1564 case LTT_STRING:
1565 size = 0;
1566 if(fld->field_fixed == -1){
1567 fld->field_fixed = 0;
1568 }else{//0: string
1569 /* Hope my implementation is faster than strlen (Mathieu) */
1570 char *ptr=(char*)evD;
1571 size = 1;
1572 /* from gcov : many many strings are empty, make it the common case.*/
1573 while(unlikely(*ptr != '\0')) { size++; ptr++; }
1574 //size = ptr - (char*)evD + 1; //include end : '\0'
1575 }
1576 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
1577 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
1578
1579 break;
1580
1581 case LTT_STRUCT:
1582 element_number = (int) type->element_number;
1583 size = 0;
1584 /* tested with gcov */
1585 if(unlikely(fld->field_fixed == -1)){
1586 offset1 = offsetRoot;
1587 offset2 = 0;
1588 for(i=0;i<element_number;i++){
1589 size1=getFieldtypeSize(t, evT,offset1,offset2,
1590 fld->child[i], NULL, trace);
1591 if(likely(size1 > 0 && size >= 0)){
1592 size += size1;
1593 if(likely(offset1 >= 0)) offset1 += size1;
1594 offset2 += size1;
1595 }else{
1596 size = -1;
1597 offset1 = -1;
1598 offset2 = -1;
1599 }
1600 }
1601 if(unlikely(size == -1)){
1602 fld->field_fixed = 0;
1603 size = 0;
1604 }else fld->field_fixed = 1;
1605 }else if(likely(fld->field_fixed == 0)){
1606 offset1 = offsetRoot;
1607 offset2 = 0;
1608 for(i=0;unlikely(i<element_number);i++){
1609 size=getFieldtypeSize(t,evT,offset1,offset2,
1610 fld->child[i],evD+offset2, trace);
1611 offset1 += size;
1612 offset2 += size;
1613 }
1614 size = offset2;
1615 }else size = fld->field_size;
1616 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
1617 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
1618 break;
1619
1620 default:
1621 if(unlikely(fld->field_fixed == -1)){
1622 size = (int) ltt_type_size(trace, type);
1623 fld->field_fixed = 1;
1624 }else size = fld->field_size;
1625 if(unlikely(!evD)){
1626 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
1627 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
1628 }
1629 break;
1630 }
1631 }
1632
1633 fld->offset_root = offsetRoot;
1634 fld->offset_parent = offsetParent;
1635 fld->field_size = size;
1636
1637 end_getFieldtypeSize:
1638
1639 return size;
1640 }
1641
1642
1643 /*****************************************************************************
1644 *Function name
1645 * getIntNumber : get an integer number
1646 *Input params
1647 * size : the size of the integer
1648 * evD : the event data
1649 *Return value
1650 * gint64 : a 64 bits integer
1651 ****************************************************************************/
1652
1653 gint64 getIntNumber(gboolean reverse_byte_order, int size, void *evD)
1654 {
1655 gint64 i;
1656
1657 switch(size) {
1658 case 1: i = *((gint8*)evD); break;
1659 case 2: i = ltt_get_int16(reverse_byte_order, evD); break;
1660 case 4: i = ltt_get_int32(reverse_byte_order, evD); break;
1661 case 8: i = ltt_get_int64(reverse_byte_order, evD); break;
1662 default: i = ltt_get_int64(reverse_byte_order, evD);
1663 g_critical("getIntNumber : integer size %d unknown", size);
1664 break;
1665 }
1666
1667 return i;
1668 }
1669 #if 0
1670 /*****************************************************************************
1671 *Function name
1672 * getDataEndianType : get the data type size and endian type of the local
1673 * machine
1674 *Input params
1675 * size : size of data type
1676 * endian : endian type, little or big
1677 ****************************************************************************/
1678
1679 void getDataEndianType(LttArchSize * size, LttArchEndian * endian)
1680 {
1681 int i = 1;
1682 char c = (char) i;
1683 int sizeInt=sizeof(int), sizeLong=sizeof(long), sizePointer=sizeof(void *);
1684
1685 if(c == 1) *endian = LTT_LITTLE_ENDIAN;
1686 else *endian = LTT_BIG_ENDIAN;
1687
1688 if(sizeInt == 2 && sizeLong == 4 && sizePointer == 4)
1689 *size = LTT_LP32;
1690 else if(sizeInt == 4 && sizeLong == 4 && sizePointer == 4)
1691 *size = LTT_ILP32;
1692 else if(sizeInt == 4 && sizeLong == 8 && sizePointer == 8)
1693 *size = LTT_LP64;
1694 else if(sizeInt == 8 && sizeLong == 8 && sizePointer == 8)
1695 *size = LTT_ILP64;
1696 else *size = LTT_UNKNOWN;
1697 }
1698 #endif //0
1699 /* get the node name of the system */
1700
1701 char * ltt_trace_system_description_node_name (LttSystemDescription * s)
1702 {
1703 return s->node_name;
1704 }
1705
1706
1707 /* get the domain name of the system */
1708
1709 char * ltt_trace_system_description_domain_name (LttSystemDescription * s)
1710 {
1711 return s->domain_name;
1712 }
1713
1714
1715 /* get the description of the system */
1716
1717 char * ltt_trace_system_description_description (LttSystemDescription * s)
1718 {
1719 return s->description;
1720 }
1721
1722
1723 /* get the start time of the trace */
1724
1725 LttTime ltt_trace_system_description_trace_start_time(LttSystemDescription *s)
1726 {
1727 return s->trace_start;
1728 }
1729
1730
1731 LttTracefile *ltt_tracefile_new()
1732 {
1733 return g_new(LttTracefile, 1);
1734 }
1735
1736 void ltt_tracefile_destroy(LttTracefile *tf)
1737 {
1738 g_free(tf);
1739 }
1740
1741 void ltt_tracefile_copy(LttTracefile *dest, const LttTracefile *src)
1742 {
1743 *dest = *src;
1744 }
1745
This page took 0.156671 seconds and 5 git commands to generate.