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