many compile 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) {
0f7f40c1 526 t->reverse_byte_order = 1;
1a2ceb63 527 } else if(sys_description->endian == LTT_BIG_ENDIAN
528 && G_BYTE_ORDER != G_BIG_ENDIAN) {
0f7f40c1 529 t->reverse_byte_order = 1;
530 } else t->reverse_byte_order = 0;
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
0f7f40c1 1089 event->event_id = ltt_get_uint16(t->trace->reverse_byte_order, 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
0f7f40c1 1096 event->time_delta = ltt_get_uint32(t->trace->reverse_byte_order, 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;
0f7f40c1 1207 tf->cur_cycle_count = ltt_get_uint32(tf->trace->reverse_byte_order, tf->cur_event_pos + EVENT_ID_SIZE);
39ae3eed 1208
6cd62ccf 1209 getCyclePerNsec(tf);
2dee981d 1210
21ff84a0 1211 tf->overflow_nsec =
1a2ceb63 1212 (-((double)
0f7f40c1 1213 (ltt_get_uint32(tf->trace->reverse_byte_order,
1214 &tf->a_block_start->cycle_count)&0xFFFFFFFF))
21ff84a0 1215 * tf->nsec_per_cycle);
6cd62ccf 1216
62e55dd6 1217 tf->current_event_time = getEventTime(tf);
40331ba8 1218
6cd62ccf 1219 return 0;
1220}
1221
1222/*****************************************************************************
1223 *Function name
1224 * updateTracefile : reinitialize the info of the block which is already
1225 * in the buffer
1226 *Input params
1227 * tf : tracefile
1228 ****************************************************************************/
1229
963b5f2d 1230void updateTracefile(LttTracefile * tf)
6cd62ccf 1231{
963b5f2d 1232 tf->which_event = 1;
40331ba8 1233 tf->cur_event_pos = tf->buffer;
62e55dd6 1234 tf->current_event_time = getEventTime(tf);
6cd62ccf 1235 tf->cur_heart_beat_number = 0;
1236
1237 tf->prev_event_time.tv_sec = 0;
1238 tf->prev_event_time.tv_nsec = 0;
2dee981d 1239 tf->count = 0;
1240
1a2ceb63 1241 tf->overflow_nsec =
0f7f40c1 1242 (-((double)ltt_get_uint32(tf->trace->reverse_byte_order,
1243 &tf->a_block_start->cycle_count))
21ff84a0 1244 * tf->nsec_per_cycle);
2dee981d 1245
6cd62ccf 1246}
1247
1248/*****************************************************************************
1249 *Function name
1250 * skipEvent : go to the next event, update the fields of the current event
1251 *Input params
1252 * t : tracefile
1253 *return value
1254 * 0 : success
6cd62ccf 1255 * ERANGE : event id is out of range
1256 ****************************************************************************/
1257
963b5f2d 1258int skipEvent(LttTracefile * t)
6cd62ccf 1259{
8d1e6362 1260 int evId;
6cd62ccf 1261 void * evData;
963b5f2d 1262 LttEventType * evT;
1263 LttField * rootFld;
6cd62ccf 1264
0f7f40c1 1265 evId = ltt_get_uint16(t->trace->reverse_byte_order, t->cur_event_pos);
6cd62ccf 1266 evData = t->cur_event_pos + EVENT_HEADER_SIZE;
6cd62ccf 1267
908f42fa 1268 evT = ltt_trace_eventtype_get(t->trace,(unsigned)evId);
47a166fc 1269
1d1df11d 1270 if(likely(evT)) rootFld = evT->root_field;
908f42fa 1271 else return ERANGE;
6cd62ccf 1272
1d1df11d 1273 if(likely(rootFld)){
908f42fa 1274 //event has string/sequence or the last event is not the same event
1d1df11d 1275 if(likely((evT->latest_block!=t->which_block || evT->latest_event!=t->which_event)
1276 && rootFld->field_fixed == 0)){
908f42fa 1277 setFieldsOffset(t, evT, evData, t->trace);
47a166fc 1278 }
908f42fa 1279 t->cur_event_pos += EVENT_HEADER_SIZE + rootFld->field_size;
1280 }else t->cur_event_pos += EVENT_HEADER_SIZE;
1281
1282 evT->latest_block = t->which_block;
1283 evT->latest_event = t->which_event;
1284
6cd62ccf 1285 //the next event is in the next block
1d1df11d 1286 if(unlikely(evId == TRACE_BLOCK_END)){
bdc36259 1287 t->cur_event_pos = t->buffer + t->block_size;
6cd62ccf 1288 }else{
0f7f40c1 1289 t->cur_cycle_count = ltt_get_uint32(t->trace->reverse_byte_order,
1290 t->cur_event_pos + EVENT_ID_SIZE);
6cd62ccf 1291 t->which_event++;
62e55dd6 1292 t->current_event_time = getEventTime(t);
6cd62ccf 1293 }
1294
1295 return 0;
1296}
1297
18206708 1298
6cd62ccf 1299/*****************************************************************************
1300 *Function name
1301 * getCyclePerNsec : calculate cycles per nsec for current block
507915ee 1302 * MD: should have tracefile_read the whole block, so we know the
1303 * total of cycles in it before being called.
6cd62ccf 1304 *Input Params
1305 * t : tracefile
1306 ****************************************************************************/
1307
963b5f2d 1308void getCyclePerNsec(LttTracefile * t)
6cd62ccf 1309{
963b5f2d 1310 LttTime lBufTotalTime; /* Total time for this buffer */
887208b7 1311 double lBufTotalNSec; /* Total time for this buffer in nsecs */
8ee1c3d5 1312 LttCycleCount lBufTotalCycle;/* Total cycles for this buffer */
6cd62ccf 1313
1314 /* Calculate the total time for this buffer */
308711e5 1315 lBufTotalTime = ltt_time_sub(t->a_block_end->time, t->a_block_start->time);
6cd62ccf 1316
1317 /* Calculate the total cycles for this bufffer */
0f7f40c1 1318 lBufTotalCycle = ltt_get_uint32(t->trace->reverse_byte_order,
1319 &t->a_block_end->cycle_count);
1320 lBufTotalCycle -= ltt_get_uint32(t->trace->reverse_byte_order,
1321 &t->a_block_start->cycle_count);
6cd62ccf 1322
8ee1c3d5 1323 /* Convert the total time to double */
887208b7 1324 lBufTotalNSec = ltt_time_to_double(lBufTotalTime);
6cd62ccf 1325
887208b7 1326 t->nsec_per_cycle = (double)lBufTotalNSec / (double)lBufTotalCycle;
8ee1c3d5 1327
2dee981d 1328 /* Pre-multiply one overflow (2^32 cycles) by nsec_per_cycle */
21ff84a0 1329 t->one_overflow_nsec = t->nsec_per_cycle * (double)0x100000000ULL;
2dee981d 1330
6cd62ccf 1331}
1332
1333/****************************************************************************
1334 *Function name
1335 * getEventTime : obtain the time of an event
887208b7 1336 * NOTE : this function _really_ is on critical path.
6cd62ccf 1337 *Input params
1338 * tf : tracefile
1339 *Return value
963b5f2d 1340 * LttTime : the time of the event
6cd62ccf 1341 ****************************************************************************/
1342
8959a0c8 1343static inline LttTime getEventTime(LttTracefile * tf)
6cd62ccf 1344{
963b5f2d 1345 LttTime time;
1346 LttCycleCount cycle_count; // cycle count for the current event
2dee981d 1347 //LttCycleCount lEventTotalCycle; // Total cycles from start for event
1348 gint64 lEventNSec; // Total nsecs from start for event
963b5f2d 1349 LttTime lTimeOffset; // Time offset in struct LttTime
cbd41522 1350 guint16 evId;
e4eced0f 1351
0f7f40c1 1352 evId = ltt_get_uint16(tf->trace->reverse_byte_order,
1353 tf->cur_event_pos);
ac849774 1354
0f7f40c1 1355 cycle_count = ltt_get_uint32(tf->trace->reverse_byte_order,
1356 tf->cur_event_pos + EVENT_ID_SIZE);
e4eced0f 1357
dfb73233 1358 gboolean comp_count = cycle_count < tf->pre_cycle_count;
bbf28e50 1359
dfb73233 1360 tf->pre_cycle_count = cycle_count;
1361
1362 if(unlikely(comp_count)) {
bbf28e50 1363 /* Overflow */
dfb73233 1364 tf->overflow_nsec += tf->one_overflow_nsec;
1365 tf->count++; //increment overflow count
1366 }
1367
1368 if(unlikely(evId == TRACE_BLOCK_START)) {
1369 lEventNSec = 0;
1370 } else if(unlikely(evId == TRACE_BLOCK_END)) {
21ff84a0 1371 lEventNSec = ((double)
0f7f40c1 1372 (ltt_get_uint32(tf->trace->reverse_byte_order,
1373 &tf->a_block_end->cycle_count)
1374 - ltt_get_uint32(tf->trace->reverse_byte_order,
1375 &tf->a_block_start->cycle_count))
21ff84a0 1376 * tf->nsec_per_cycle);
dfb73233 1377 }
dfb73233 1378#if 0
bbf28e50 1379 /* If you want to make heart beat a special case and use their own 64 bits
1380 * TSC, activate this.
1381 */
dfb73233 1382 else if(unlikely(evId == TRACE_TIME_HEARTBEAT)) {
1383
1384 tf->last_heartbeat = (TimeHeartbeat*)(tf->cur_event_pos+EVENT_HEADER_SIZE);
1385 lEventNSec = ((double)(tf->last_heartbeat->cycle_count
1386 - tf->a_block_start->cycle_count)
1387 * tf->nsec_per_cycle);
1388 }
1389#endif //0
1390 else {
21ff84a0 1391 lEventNSec = (gint64)((double)cycle_count * tf->nsec_per_cycle)
dfb73233 1392 +tf->overflow_nsec;
1393 }
1394
2dee981d 1395 lTimeOffset = ltt_time_from_uint64(lEventNSec);
1396
308711e5 1397 time = ltt_time_add(tf->a_block_start->time, lTimeOffset);
e4eced0f 1398
6cd62ccf 1399 return time;
1400}
1401
1402/*****************************************************************************
1403 *Function name
1404 * setFieldsOffset : set offset of the fields
1405 *Input params
1406 * tracefile : opened trace file
1407 * evT : the event type
1408 * evD : event data, it may be NULL
1409 ****************************************************************************/
1410
40331ba8 1411void setFieldsOffset(LttTracefile *tf,LttEventType *evT,void *evD,LttTrace* t)
6cd62ccf 1412{
963b5f2d 1413 LttField * rootFld = evT->root_field;
6cd62ccf 1414 // rootFld->base_address = evD;
1415
1d1df11d 1416 if(likely(rootFld))
8710c6c7 1417 rootFld->field_size = getFieldtypeSize(tf, evT, 0,0,rootFld, evD,t);
6cd62ccf 1418}
1419
1420/*****************************************************************************
1421 *Function name
1422 * getFieldtypeSize: get the size of the field type (primitive type)
1423 *Input params
1424 * tracefile : opened trace file
1425 * evT : event type
1426 * offsetRoot : offset from the root
1427 * offsetParent : offset from the parrent
1428 * fld : field
1429 * evD : event data, it may be NULL
1430 *Return value
1431 * int : size of the field
1432 ****************************************************************************/
1433
21182d4a 1434static inline gint getFieldtypeSize(LttTracefile * t,
1435 LttEventType * evT, gint offsetRoot,
1436 gint offsetParent, LttField * fld, void *evD, LttTrace *trace)
6cd62ccf 1437{
21182d4a 1438 gint size, size1, element_number, i, offset1, offset2;
963b5f2d 1439 LttType * type = fld->field_type;
6cd62ccf 1440
21182d4a 1441 if(unlikely(t && evT->latest_block==t->which_block &&
1442 evT->latest_event==t->which_event)){
1443 size = fld->field_size;
1444 goto end_getFieldtypeSize;
a0d63196 1445 } else {
1446 /* This likely has been tested with gcov : half of them.. */
1447 if(unlikely(fld->field_fixed == 1)){
1448 /* tested : none */
1449 if(unlikely(fld == evT->root_field)) {
1450 size = fld->field_size;
1451 goto end_getFieldtypeSize;
1452 }
21182d4a 1453 }
6cd62ccf 1454
a0d63196 1455 /* From gcov profiling : half string, half struct, can we gain something
1456 * from that ? (Mathieu) */
1457 switch(type->type_class) {
1458 case LTT_ARRAY:
1459 element_number = (int) type->element_number;
1460 if(fld->field_fixed == -1){
1461 size = getFieldtypeSize(t, evT, offsetRoot,
1462 0,fld->child[0], NULL, trace);
1463 if(size == 0){ //has string or sequence
1464 fld->field_fixed = 0;
1465 }else{
1466 fld->field_fixed = 1;
1467 size *= element_number;
1468 }
1469 }else if(fld->field_fixed == 0){// has string or sequence
1470 size = 0;
1471 for(i=0;i<element_number;i++){
1472 size += getFieldtypeSize(t, evT, offsetRoot+size,size,
1473 fld->child[0], evD+size, trace);
1474 }
1475 }else size = fld->field_size;
1476 if(unlikely(!evD)){
1477 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
1478 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
1479 }
1480
1481 break;
1482
1483 case LTT_SEQUENCE:
1484 size1 = (int) ltt_type_size(trace, type);
1485 if(fld->field_fixed == -1){
1486 fld->sequ_number_size = size1;
cf74a6f1 1487 fld->field_fixed = 0;
a0d63196 1488 size = getFieldtypeSize(t, evT, offsetRoot,
1489 0,fld->child[0], NULL, trace);
1490 fld->element_size = size;
1491 }else{//0: sequence
0f7f40c1 1492 element_number = getIntNumber(t->trace->reverse_byte_order,size1,evD);
a0d63196 1493 type->element_number = element_number;
1494 if(fld->element_size > 0){
1495 size = element_number * fld->element_size;
1496 }else{//sequence has string or sequence
1497 size = 0;
1498 for(i=0;i<element_number;i++){
1499 size += getFieldtypeSize(t, evT, offsetRoot+size+size1,size+size1,
1500 fld->child[0], evD+size+size1, trace);
1501 }
1502 }
1503 size += size1;
cf74a6f1 1504 }
a0d63196 1505 if(unlikely(!evD)){
1506 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
1507 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
1508 }
1509
1510 break;
1511
1512 case LTT_STRING:
cf74a6f1 1513 size = 0;
a0d63196 1514 if(fld->field_fixed == -1){
1515 fld->field_fixed = 0;
1516 }else{//0: string
1517 /* Hope my implementation is faster than strlen (Mathieu) */
1518 char *ptr=(char*)evD;
1519 size = 1;
1520 /* from gcov : many many strings are empty, make it the common case.*/
1521 while(unlikely(*ptr != '\0')) { size++; ptr++; }
1522 //size = ptr - (char*)evD + 1; //include end : '\0'
cf74a6f1 1523 }
a0d63196 1524 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
1525 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
cf74a6f1 1526
a0d63196 1527 break;
1528
1529 case LTT_STRUCT:
1530 element_number = (int) type->element_number;
1531 size = 0;
1532 /* tested with gcov */
1533 if(unlikely(fld->field_fixed == -1)){
1534 offset1 = offsetRoot;
1535 offset2 = 0;
cf74a6f1 1536 for(i=0;i<element_number;i++){
a0d63196 1537 size1=getFieldtypeSize(t, evT,offset1,offset2,
1538 fld->child[i], NULL, trace);
1539 if(likely(size1 > 0 && size >= 0)){
1540 size += size1;
1541 if(likely(offset1 >= 0)) offset1 += size1;
1542 offset2 += size1;
1543 }else{
1544 size = -1;
1545 offset1 = -1;
1546 offset2 = -1;
1547 }
cf74a6f1 1548 }
a0d63196 1549 if(unlikely(size == -1)){
1550 fld->field_fixed = 0;
1551 size = 0;
1552 }else fld->field_fixed = 1;
1553 }else if(likely(fld->field_fixed == 0)){
1554 offset1 = offsetRoot;
1555 offset2 = 0;
1556 for(i=0;unlikely(i<element_number);i++){
1557 size=getFieldtypeSize(t,evT,offset1,offset2,
1558 fld->child[i],evD+offset2, trace);
1559 offset1 += size;
1560 offset2 += size;
1561 }
1562 size = offset2;
1563 }else size = fld->field_size;
d37b2aaa 1564 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
1565 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
a0d63196 1566 break;
cf74a6f1 1567
a0d63196 1568 default:
1569 if(unlikely(fld->field_fixed == -1)){
1570 size = (int) ltt_type_size(trace, type);
1571 fld->field_fixed = 1;
1572 }else size = fld->field_size;
1573 if(unlikely(!evD)){
1574 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
1575 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
1576 }
1577 break;
1578 }
cf74a6f1 1579 }
1580
6cd62ccf 1581 fld->offset_root = offsetRoot;
1582 fld->offset_parent = offsetParent;
6cd62ccf 1583 fld->field_size = size;
1584
21182d4a 1585end_getFieldtypeSize:
1586
6cd62ccf 1587 return size;
1588}
1589
6cd62ccf 1590
1591/*****************************************************************************
1592 *Function name
1593 * getIntNumber : get an integer number
1594 *Input params
1595 * size : the size of the integer
1596 * evD : the event data
1597 *Return value
cf74a6f1 1598 * gint64 : a 64 bits integer
6cd62ccf 1599 ****************************************************************************/
1600
0f7f40c1 1601gint64 getIntNumber(gboolean reverse_byte_order, int size, void *evD)
6cd62ccf 1602{
cbd41522 1603 gint64 i;
cf74a6f1 1604
1605 switch(size) {
1a2ceb63 1606 case 1: i = *((gint8*)evD); break;
0f7f40c1 1607 case 2: i = ltt_get_int16(reverse_byte_order, evD); break;
1608 case 4: i = ltt_get_int32(reverse_byte_order, evD); break;
1609 case 8: i = ltt_get_int64(reverse_byte_order, evD); break;
1610 default: i = ltt_get_int64(reverse_byte_order, evD);
cf74a6f1 1611 g_critical("getIntNumber : integer size %d unknown", size);
1612 break;
1613 }
1614
1a2ceb63 1615 return i;
6cd62ccf 1616}
0f7f40c1 1617#if 0
6cd62ccf 1618/*****************************************************************************
1619 *Function name
1620 * getDataEndianType : get the data type size and endian type of the local
1621 * machine
1622 *Input params
1623 * size : size of data type
1624 * endian : endian type, little or big
1625 ****************************************************************************/
1626
963b5f2d 1627void getDataEndianType(LttArchSize * size, LttArchEndian * endian)
6cd62ccf 1628{
1629 int i = 1;
1630 char c = (char) i;
1631 int sizeInt=sizeof(int), sizeLong=sizeof(long), sizePointer=sizeof(void *);
1632
1633 if(c == 1) *endian = LTT_LITTLE_ENDIAN;
1634 else *endian = LTT_BIG_ENDIAN;
1635
1636 if(sizeInt == 2 && sizeLong == 4 && sizePointer == 4)
1637 *size = LTT_LP32;
1638 else if(sizeInt == 4 && sizeLong == 4 && sizePointer == 4)
1639 *size = LTT_ILP32;
1640 else if(sizeInt == 4 && sizeLong == 8 && sizePointer == 8)
1641 *size = LTT_LP64;
1642 else if(sizeInt == 8 && sizeLong == 8 && sizePointer == 8)
1643 *size = LTT_ILP64;
1644 else *size = LTT_UNKNOWN;
1645}
0f7f40c1 1646#endif //0
a5dcde2f 1647/* get the node name of the system */
1648
1649char * ltt_trace_system_description_node_name (LttSystemDescription * s)
1650{
1651 return s->node_name;
1652}
1653
1654
1655/* get the domain name of the system */
1656
1657char * ltt_trace_system_description_domain_name (LttSystemDescription * s)
1658{
1659 return s->domain_name;
1660}
1661
1662
1663/* get the description of the system */
1664
1665char * ltt_trace_system_description_description (LttSystemDescription * s)
1666{
1667 return s->description;
1668}
1669
1670
1671/* get the start time of the trace */
1672
1673LttTime ltt_trace_system_description_trace_start_time(LttSystemDescription *s)
1674{
1675 return s->trace_start;
1676}
1677
18206708 1678
1679LttTracefile *ltt_tracefile_new()
1680{
1681 return g_new(LttTracefile, 1);
1682}
1683
1684void ltt_tracefile_destroy(LttTracefile *tf)
1685{
1686 g_free(tf);
1687}
1688
1689void ltt_tracefile_copy(LttTracefile *dest, const LttTracefile *src)
1690{
1691 *dest = *src;
1692}
1693
This page took 0.13497 seconds and 4 git commands to generate.