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