add missing config.h include
[lttv.git] / ltt / branches / poly / ltt / tracefile.c
CommitLineData
449cb9d7 1/* This file is part of the Linux Trace Toolkit viewer
3aee1200 2 * Copyright (C) 2005 Mathieu Desnoyers
449cb9d7 3 *
3aee1200 4 * Complete rewrite from the original version made by XangXiu Yang.
5 *
1b44b0b5 6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License Version 2.1 as published by the Free Software Foundation.
449cb9d7 9 *
1b44b0b5 10 * This library is distributed in the hope that it will be useful,
449cb9d7 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1b44b0b5 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
449cb9d7 14 *
1b44b0b5 15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
449cb9d7 19 */
20
4e4d11b3 21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
6cd62ccf 25#include <stdio.h>
26#include <fcntl.h>
8d1e6362 27#include <string.h>
28#include <dirent.h>
6cd62ccf 29#include <sys/stat.h>
30#include <sys/types.h>
8d1e6362 31#include <errno.h>
32#include <unistd.h>
42db9bf1 33#include <math.h>
cdf90f40 34#include <glib.h>
3aee1200 35#include <malloc.h>
36#include <sys/mman.h>
dd3a6d39 37#include <string.h>
6cd62ccf 38
ef35d837 39// For realpath
40#include <limits.h>
41#include <stdlib.h>
42
43
6cd62ccf 44#include "parser.h"
a5dcde2f 45#include <ltt/ltt.h>
46#include "ltt-private.h"
963b5f2d 47#include <ltt/trace.h>
c02ea99f 48#include <ltt/event.h>
29af7cfd 49//#include <ltt/type.h>
1a2ceb63 50#include <ltt/ltt-types.h>
bb38a290 51#include <ltt/marker.h>
3aee1200 52
53/* Facility names used in this file */
54
55GQuark LTT_FACILITY_NAME_HEARTBEAT,
d1bb700c 56 LTT_EVENT_NAME_HEARTBEAT,
57 LTT_EVENT_NAME_HEARTBEAT_FULL;
3aee1200 58GQuark LTT_TRACEFILE_NAME_FACILITIES;
59
86005ded 60#ifndef g_open
61#define g_open open
62#endif
63
64
51b5991e 65#define __UNUSED__ __attribute__((__unused__))
6cd62ccf 66
a1062ddd 67#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
3aee1200 68
69#ifndef g_debug
a1062ddd 70#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
3aee1200 71#endif
a1062ddd 72
45e14832 73#define g_close close
8959a0c8 74
b77d1b57 75/* Those macros must be called from within a function where page_size is a known
76 * variable */
77#define PAGE_MASK (~(page_size-1))
78#define PAGE_ALIGN(addr) (((addr)+page_size-1)&PAGE_MASK)
79
6cd62ccf 80/* set the offset of the fields belonging to the event,
81 need the information of the archecture */
f104d082 82//void set_fields_offsets(LttTracefile *tf, LttEventType *event_type);
eed2ef37 83//size_t get_fields_offsets(LttTracefile *tf, LttEventType *event_type, void *data);
6cd62ccf 84
3aee1200 85/* get the size of the field type according to
86 * The facility size information. */
f104d082 87#if 0
3aee1200 88static inline void preset_field_type_size(LttTracefile *tf,
89 LttEventType *event_type,
90 off_t offset_root, off_t offset_parent,
91 enum field_status *fixed_root, enum field_status *fixed_parent,
92 LttField *field);
f104d082 93#endif //0
6cd62ccf 94
3aee1200 95/* map a fixed size or a block information from the file (fd) */
96static gint map_block(LttTracefile * tf, guint block_num);
97
98/* calculate nsec per cycles for current block */
791dffa6 99#if 0
100static guint32 calc_nsecs_per_cycle(LttTracefile * t);
101static guint64 cycles_2_ns(LttTracefile *tf, guint64 cycles);
102#endif //0
6cd62ccf 103
3aee1200 104/* go to the next event */
105static int ltt_seek_next_event(LttTracefile *tf);
6cd62ccf 106
3c165eaf 107//void ltt_update_event_size(LttTracefile *tf);
eed2ef37 108
3c165eaf 109static int open_tracefiles(LttTrace *trace, gchar *root_path,
110 gchar *relative_path);
111static int ltt_process_facility_tracefile(LttTracefile *tf);
112static void ltt_tracefile_time_span_get(LttTracefile *tf,
113 LttTime *start, LttTime *end);
114static void group_time_span_get(GQuark name, gpointer data, gpointer user_data);
115static gint map_block(LttTracefile * tf, guint block_num);
116static int ltt_seek_next_event(LttTracefile *tf);
117static void __attribute__((constructor)) init(void);
118static void ltt_update_event_size(LttTracefile *tf);
119//void precompute_offsets(LttFacility *fac, LttEventType *event);
2312de30 120
3aee1200 121#if 0
43da6a59 122/* Functions to parse system.xml file (using glib xml parser) */
51b5991e 123static void parser_start_element (GMarkupParseContext __UNUSED__ *context,
43da6a59 124 const gchar *element_name,
125 const gchar **attribute_names,
126 const gchar **attribute_values,
127 gpointer user_data,
128 GError **error)
129{
130 int i=0;
131 LttSystemDescription* des = (LttSystemDescription* )user_data;
132 if(strcmp("system", element_name)){
2a74fbf4 133 *error = g_error_new(G_MARKUP_ERROR,
134 G_LOG_LEVEL_WARNING,
135 "This is not system.xml file");
136 return;
43da6a59 137 }
138
139 while(attribute_names[i]){
140 if(strcmp("node_name", attribute_names[i])==0){
141 des->node_name = g_strdup(attribute_values[i]);
142 }else if(strcmp("domainname", attribute_names[i])==0){
143 des->domain_name = g_strdup(attribute_values[i]);
144 }else if(strcmp("cpu", attribute_names[i])==0){
145 des->nb_cpu = atoi(attribute_values[i]);
146 }else if(strcmp("arch_size", attribute_names[i])==0){
147 if(strcmp(attribute_values[i],"LP32") == 0) des->size = LTT_LP32;
148 else if(strcmp(attribute_values[i],"ILP32") == 0) des->size = LTT_ILP32;
149 else if(strcmp(attribute_values[i],"LP64") == 0) des->size = LTT_LP64;
150 else if(strcmp(attribute_values[i],"ILP64") == 0) des->size = LTT_ILP64;
151 else if(strcmp(attribute_values[i],"UNKNOWN") == 0) des->size = LTT_UNKNOWN;
152 }else if(strcmp("endian", attribute_names[i])==0){
153 if(strcmp(attribute_values[i],"LITTLE_ENDIAN") == 0)
154 des->endian = LTT_LITTLE_ENDIAN;
155 else if(strcmp(attribute_values[i],"BIG_ENDIAN") == 0)
156 des->endian = LTT_BIG_ENDIAN;
157 }else if(strcmp("kernel_name", attribute_names[i])==0){
158 des->kernel_name = g_strdup(attribute_values[i]);
159 }else if(strcmp("kernel_release", attribute_names[i])==0){
160 des->kernel_release = g_strdup(attribute_values[i]);
161 }else if(strcmp("kernel_version", attribute_names[i])==0){
162 des->kernel_version = g_strdup(attribute_values[i]);
163 }else if(strcmp("machine", attribute_names[i])==0){
164 des->machine = g_strdup(attribute_values[i]);
165 }else if(strcmp("processor", attribute_names[i])==0){
166 des->processor = g_strdup(attribute_values[i]);
167 }else if(strcmp("hardware_platform", attribute_names[i])==0){
168 des->hardware_platform = g_strdup(attribute_values[i]);
169 }else if(strcmp("operating_system", attribute_names[i])==0){
170 des->operating_system = g_strdup(attribute_values[i]);
171 }else if(strcmp("ltt_major_version", attribute_names[i])==0){
172 des->ltt_major_version = atoi(attribute_values[i]);
173 }else if(strcmp("ltt_minor_version", attribute_names[i])==0){
174 des->ltt_minor_version = atoi(attribute_values[i]);
175 }else if(strcmp("ltt_block_size", attribute_names[i])==0){
176 des->ltt_block_size = atoi(attribute_values[i]);
177 }else{
2a74fbf4 178 *error = g_error_new(G_MARKUP_ERROR,
179 G_LOG_LEVEL_WARNING,
180 "Not a valid attribute");
181 return;
43da6a59 182 }
183 i++;
184 }
185}
186
51b5991e 187static void parser_characters (GMarkupParseContext __UNUSED__ *context,
43da6a59 188 const gchar *text,
51b5991e 189 gsize __UNUSED__ text_len,
43da6a59 190 gpointer user_data,
51b5991e 191 GError __UNUSED__ **error)
43da6a59 192{
193 LttSystemDescription* des = (LttSystemDescription* )user_data;
194 des->description = g_strdup(text);
195}
3aee1200 196#endif //0
f104d082 197
3c165eaf 198#if 0
77175651 199LttFacility *ltt_trace_get_facility_by_num(LttTrace *t,
3aee1200 200 guint num)
201{
202 g_assert(num < t->facilities_by_num->len);
203
204 return &g_array_index(t->facilities_by_num, LttFacility, num);
205
206}
3c165eaf 207#endif //0
43da6a59 208
b56dcdf2 209guint ltt_trace_get_num_cpu(LttTrace *t)
210{
211 return t->num_cpu;
212}
213
43da6a59 214
b7576a11 215/* trace can be NULL
216 *
217 * Return value : 0 success, 1 bad tracefile
218 */
219int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t)
220{
221 guint32 *magic_number = (guint32*)header;
222 struct ltt_trace_header_any *any = (struct ltt_trace_header_any *)header;
223
224 if(*magic_number == LTT_MAGIC_NUMBER)
225 tf->reverse_bo = 0;
226 else if(*magic_number == LTT_REV_MAGIC_NUMBER)
227 tf->reverse_bo = 1;
228 else /* invalid magic number, bad tracefile ! */
229 return 1;
230
231 /* Get float byte order : might be different from int byte order
232 * (or is set to 0 if the trace has no float (kernel trace)) */
233 tf->float_word_order = any->float_word_order;
256a5b3a 234 tf->alignment = any->alignment;
90440c06 235 tf->has_heartbeat = any->has_heartbeat;
b7576a11 236
237 if(t) {
238 t->arch_type = ltt_get_uint32(LTT_GET_BO(tf),
239 &any->arch_type);
240 t->arch_variant = ltt_get_uint32(LTT_GET_BO(tf),
241 &any->arch_variant);
242 t->arch_size = any->arch_size;
243 t->ltt_major_version = any->major_version;
244 t->ltt_minor_version = any->minor_version;
245 t->flight_recorder = any->flight_recorder;
3c165eaf 246 // t->compact_facilities = NULL;
b7576a11 247 }
248
f2a74ed3 249 printf("init size : %d\n", sizeof(LttTracefile));
250
b7576a11 251
252 switch(any->major_version) {
253
254 case 0:
3c165eaf 255 g_warning("Unsupported trace version : %hhu.%hhu",
256 any->major_version, any->minor_version);
257 return 1;
258 break;
259 case 1:
b7576a11 260 switch(any->minor_version) {
3c165eaf 261 case 0:
b7576a11 262 {
3c165eaf 263 struct ltt_trace_header_1_0 *vheader =
264 (struct ltt_trace_header_1_0 *)header;
823820eb 265 tf->buffer_header_size =
266 sizeof(struct ltt_block_start_header)
3c165eaf 267 + sizeof(struct ltt_trace_header_1_0);
62e4e7bf 268 tf->tsc_lsb_truncate = vheader->tsc_lsb_truncate;
269 tf->tscbits = vheader->tscbits;
270 tf->tsc_msb_cutoff = 32 - tf->tsc_lsb_truncate - tf->tscbits;
dd3a6d39 271 tf->tsc_mask = ((1ULL << (tf->tscbits))-1);
272 tf->tsc_mask = tf->tsc_mask << tf->tsc_lsb_truncate;
62e4e7bf 273 tf->tsc_mask_next_bit = (1ULL<<(tf->tscbits));
274 tf->tsc_mask_next_bit = tf->tsc_mask_next_bit << tf->tsc_lsb_truncate;
e939e5b2 275 if(t) {
276 t->start_freq = ltt_get_uint64(LTT_GET_BO(tf),
277 &vheader->start_freq);
a3999b49 278 t->freq_scale = ltt_get_uint32(LTT_GET_BO(tf),
279 &vheader->freq_scale);
e939e5b2 280 t->start_tsc = ltt_get_uint64(LTT_GET_BO(tf),
281 &vheader->start_tsc);
282 t->start_monotonic = ltt_get_uint64(LTT_GET_BO(tf),
283 &vheader->start_monotonic);
284 t->start_time.tv_sec = ltt_get_uint64(LTT_GET_BO(tf),
285 &vheader->start_time_sec);
286 t->start_time.tv_nsec = ltt_get_uint64(LTT_GET_BO(tf),
287 &vheader->start_time_usec);
288 t->start_time.tv_nsec *= 1000; /* microsec to nanosec */
289
290 t->start_time_from_tsc = ltt_time_from_uint64(
c7f86478 291 (double)t->start_tsc
292 * (1000000000.0 / tf->trace->freq_scale)
62e4e7bf 293 / (double)t->start_freq);
294 t->compact_event_bits = 0;
e939e5b2 295 }
296 }
297 break;
b7576a11 298 default:
986e2a7c 299 g_warning("Unsupported trace version : %hhu.%hhu",
3c165eaf 300 any->major_version, any->minor_version);
b7576a11 301 return 1;
302 }
303 break;
b7576a11 304 default:
305 g_warning("Unsupported trace version : %hhu.%hhu",
306 any->major_version, any->minor_version);
307 return 1;
308 }
309
310
311 return 0;
312}
313
314
315
6cd62ccf 316/*****************************************************************************
317 *Function name
963b5f2d 318 * ltt_tracefile_open : open a trace file, construct a LttTracefile
6cd62ccf 319 *Input params
963b5f2d 320 * t : the trace containing the tracefile
321 * fileName : path name of the trace file
3aee1200 322 * tf : the tracefile structure
6cd62ccf 323 *Return value
3aee1200 324 * : 0 for success, -1 otherwise.
6cd62ccf 325 ****************************************************************************/
326
3aee1200 327gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf)
6cd62ccf 328{
963b5f2d 329 struct stat lTDFStat; /* Trace data file status */
3aee1200 330 struct ltt_block_start_header *header;
b77d1b57 331 int page_size = getpagesize();
6cd62ccf 332
333 //open the file
d3d34f49 334 tf->long_name = g_quark_from_string(fileName);
963b5f2d 335 tf->trace = t;
3865ea09 336 tf->fd = open(fileName, O_RDONLY);
6cd62ccf 337 if(tf->fd < 0){
2a74fbf4 338 g_warning("Unable to open input data file %s\n", fileName);
3aee1200 339 goto end;
6cd62ccf 340 }
341
342 // Get the file's status
343 if(fstat(tf->fd, &lTDFStat) < 0){
2a74fbf4 344 g_warning("Unable to get the status of the input data file %s\n", fileName);
3aee1200 345 goto close_file;
6cd62ccf 346 }
347
348 // Is the file large enough to contain a trace
823820eb 349 if(lTDFStat.st_size <
9ea7b94b 350 (off_t)(sizeof(struct ltt_block_start_header)
351 + sizeof(struct ltt_trace_header_any))){
8710c6c7 352 g_print("The input data file %s does not contain a trace\n", fileName);
3aee1200 353 goto close_file;
354 }
355
356 /* Temporarily map the buffer start header to get trace information */
357 /* Multiple of pages aligned head */
b77d1b57 358 tf->buffer.head = mmap(0,
9ea7b94b 359 PAGE_ALIGN(sizeof(struct ltt_block_start_header)
360 + sizeof(struct ltt_trace_header_any)), PROT_READ,
3aee1200 361 MAP_PRIVATE, tf->fd, 0);
3865ea09 362 if(tf->buffer.head == MAP_FAILED) {
3aee1200 363 perror("Error in allocating memory for buffer of tracefile");
364 goto close_file;
6cd62ccf 365 }
3865ea09 366 g_assert( ( (guint)tf->buffer.head&(8-1) ) == 0); // make sure it's aligned.
3aee1200 367
368 header = (struct ltt_block_start_header*)tf->buffer.head;
6cd62ccf 369
51551c6f 370 if(parse_trace_header(header->trace, tf, NULL)) {
371 g_warning("parse_trace_header error");
372 goto unmap_file;
373 }
3aee1200 374
6cd62ccf 375 //store the size of the file
376 tf->file_size = lTDFStat.st_size;
f628823c 377 tf->buf_size = ltt_get_uint32(LTT_GET_BO(tf), &header->buf_size);
378 tf->num_blocks = tf->file_size / tf->buf_size;
379
380 if(munmap(tf->buffer.head,
9ea7b94b 381 PAGE_ALIGN(sizeof(struct ltt_block_start_header)
382 + sizeof(struct ltt_trace_header_any)))) {
f628823c 383 g_warning("unmap size : %u\n",
9ea7b94b 384 PAGE_ALIGN(sizeof(struct ltt_block_start_header)
385 + sizeof(struct ltt_trace_header_any)));
f628823c 386 perror("munmap error");
387 g_assert(0);
388 }
3aee1200 389 tf->buffer.head = NULL;
6cd62ccf 390
963b5f2d 391 //read the first block
3aee1200 392 if(map_block(tf,0)) {
393 perror("Cannot map block for tracefile");
394 goto close_file;
395 }
396
397 return 0;
6cd62ccf 398
3aee1200 399 /* Error */
400unmap_file:
f628823c 401 if(munmap(tf->buffer.head,
9ea7b94b 402 PAGE_ALIGN(sizeof(struct ltt_block_start_header)
403 + sizeof(struct ltt_trace_header_any)))) {
f628823c 404 g_warning("unmap size : %u\n",
9ea7b94b 405 PAGE_ALIGN(sizeof(struct ltt_block_start_header)
406 + sizeof(struct ltt_trace_header_any)));
f628823c 407 perror("munmap error");
408 g_assert(0);
409 }
3aee1200 410close_file:
3865ea09 411 close(tf->fd);
3aee1200 412end:
413 return -1;
6cd62ccf 414}
415
d3d34f49 416LttTrace *ltt_tracefile_get_trace(LttTracefile *tf)
417{
418 return tf->trace;
419}
420
3aee1200 421#if 0
6cd62ccf 422/*****************************************************************************
963b5f2d 423 *Open control and per cpu tracefiles
6cd62ccf 424 ****************************************************************************/
425
45e14832 426void ltt_tracefile_open_cpu(LttTrace *t, gchar * tracefile_name)
6cd62ccf 427{
963b5f2d 428 LttTracefile * tf;
429 tf = ltt_tracefile_open(t,tracefile_name);
4a6c8e36 430 if(!tf) return;
963b5f2d 431 t->per_cpu_tracefile_number++;
432 g_ptr_array_add(t->per_cpu_tracefiles, tf);
6cd62ccf 433}
434
45e14832 435gint ltt_tracefile_open_control(LttTrace *t, gchar * control_name)
6cd62ccf 436{
963b5f2d 437 LttTracefile * tf;
c02ea99f 438 LttEvent ev;
963b5f2d 439 LttFacility * f;
963b5f2d 440 void * pos;
441 FacilityLoad fLoad;
8d1e6362 442 unsigned int i;
963b5f2d 443
444 tf = ltt_tracefile_open(t,control_name);
2a74fbf4 445 if(!tf) {
446 g_warning("ltt_tracefile_open_control : bad file descriptor");
447 return -1;
448 }
963b5f2d 449 t->control_tracefile_number++;
450 g_ptr_array_add(t->control_tracefiles,tf);
451
452 //parse facilities tracefile to get base_id
542ceddd 453 if(strcmp(&control_name[strlen(control_name)-10],"facilities") ==0){
963b5f2d 454 while(1){
c02ea99f 455 if(!ltt_tracefile_read(tf,&ev)) return 0; // end of file
40331ba8 456
c02ea99f 457 if(ev.event_id == TRACE_FACILITY_LOAD){
458 pos = ev.data;
45e14832 459 fLoad.name = (gchar*)pos;
47a166fc 460 fLoad.checksum = *(LttChecksum*)(pos + strlen(fLoad.name));
cbd41522 461 fLoad.base_code = *(guint32 *)(pos + strlen(fLoad.name) + sizeof(LttChecksum));
963b5f2d 462
463 for(i=0;i<t->facility_number;i++){
464 f = (LttFacility*)g_ptr_array_index(t->facilities,i);
465 if(strcmp(f->name,fLoad.name)==0 && fLoad.checksum==f->checksum){
466 f->base_id = fLoad.base_code;
467 break;
468 }
469 }
2a74fbf4 470 if(i==t->facility_number) {
8d1e6362 471 g_warning("Facility: %s, checksum: %u is not found",
472 fLoad.name,(unsigned int)fLoad.checksum);
2a74fbf4 473 return -1;
474 }
c02ea99f 475 }else if(ev.event_id == TRACE_BLOCK_START){
40331ba8 476 continue;
c02ea99f 477 }else if(ev.event_id == TRACE_BLOCK_END){
40331ba8 478 break;
2a74fbf4 479 }else {
8d1e6362 480 g_warning("Not valid facilities trace file");
2a74fbf4 481 return -1;
482 }
963b5f2d 483 }
484 }
2a74fbf4 485 return 0;
6cd62ccf 486}
3aee1200 487#endif //0
6cd62ccf 488
489/*****************************************************************************
490 *Function name
963b5f2d 491 * ltt_tracefile_close: close a trace file,
6cd62ccf 492 *Input params
963b5f2d 493 * t : tracefile which will be closed
6cd62ccf 494 ****************************************************************************/
495
963b5f2d 496void ltt_tracefile_close(LttTracefile *t)
6cd62ccf 497{
f628823c 498 int page_size = getpagesize();
499
3aee1200 500 if(t->buffer.head != NULL)
f628823c 501 if(munmap(t->buffer.head, PAGE_ALIGN(t->buf_size))) {
502 g_warning("unmap size : %u\n",
503 PAGE_ALIGN(t->buf_size));
504 perror("munmap error");
505 g_assert(0);
506 }
507
3865ea09 508 close(t->fd);
963b5f2d 509}
6cd62ccf 510
6cd62ccf 511
963b5f2d 512/*****************************************************************************
513 *Get system information
514 ****************************************************************************/
3aee1200 515#if 0
45e14832 516gint getSystemInfo(LttSystemDescription* des, gchar * pathname)
963b5f2d 517{
45e14832 518 int fd;
519 GIOChannel *iochan;
520 gchar *buf = NULL;
521 gsize length;
43da6a59 522
523 GMarkupParseContext * context;
2a74fbf4 524 GError * error = NULL;
43da6a59 525 GMarkupParser markup_parser =
526 {
527 parser_start_element,
8d1e6362 528 NULL,
43da6a59 529 parser_characters,
530 NULL, /* passthrough */
531 NULL /* error */
532 };
963b5f2d 533
45e14832 534 fd = g_open(pathname, O_RDONLY, 0);
535 if(fd == -1){
2a74fbf4 536 g_warning("Can not open file : %s\n", pathname);
537 return -1;
6cd62ccf 538 }
963b5f2d 539
45e14832 540 iochan = g_io_channel_unix_new(fd);
541
43da6a59 542 context = g_markup_parse_context_new(&markup_parser, 0, des,NULL);
6cd62ccf 543
45e14832 544 //while(fgets(buf,DIR_NAME_SIZE, fp) != NULL){
545 while(g_io_channel_read_line(iochan, &buf, &length, NULL, &error)
546 != G_IO_STATUS_EOF) {
547
548 if(error != NULL) {
549 g_warning("Can not read xml file: \n%s\n", error->message);
550 g_error_free(error);
551 }
552 if(!g_markup_parse_context_parse(context, buf, length, &error)){
2a74fbf4 553 if(error != NULL) {
554 g_warning("Can not parse xml file: \n%s\n", error->message);
555 g_error_free(error);
556 }
557 g_markup_parse_context_free(context);
45e14832 558
559 g_io_channel_shutdown(iochan, FALSE, &error); /* No flush */
560 if(error != NULL) {
561 g_warning("Can not close file: \n%s\n", error->message);
562 g_error_free(error);
563 }
564
565 close(fd);
2a74fbf4 566 return -1;
43da6a59 567 }
963b5f2d 568 }
2a74fbf4 569 g_markup_parse_context_free(context);
45e14832 570
571 g_io_channel_shutdown(iochan, FALSE, &error); /* No flush */
572 if(error != NULL) {
573 g_warning("Can not close file: \n%s\n", error->message);
574 g_error_free(error);
575 }
576
577 g_close(fd);
578
579 g_free(buf);
2a74fbf4 580 return 0;
6cd62ccf 581}
3aee1200 582#endif //0
6cd62ccf 583
584/*****************************************************************************
963b5f2d 585 *The following functions get facility/tracefile information
6cd62ccf 586 ****************************************************************************/
3aee1200 587#if 0
45e14832 588gint getFacilityInfo(LttTrace *t, gchar* eventdefs)
6cd62ccf 589{
45e14832 590 GDir * dir;
591 const gchar * name;
8d1e6362 592 unsigned int i,j;
963b5f2d 593 LttFacility * f;
594 LttEventType * et;
45e14832 595 gchar fullname[DIR_NAME_SIZE];
596 GError * error = NULL;
597
598 dir = g_dir_open(eventdefs, 0, &error);
963b5f2d 599
45e14832 600 if(error != NULL) {
601 g_warning("Can not open directory: %s, %s\n", eventdefs, error->message);
602 g_error_free(error);
2a74fbf4 603 return -1;
604 }
963b5f2d 605
45e14832 606 while((name = g_dir_read_name(dir)) != NULL){
607 if(!g_pattern_match_simple("*.xml", name)) continue;
608 strcpy(fullname,eventdefs);
609 strcat(fullname,name);
610 ltt_facility_open(t,fullname);
611 }
612 g_dir_close(dir);
963b5f2d 613
963b5f2d 614 for(j=0;j<t->facility_number;j++){
8710c6c7 615 f = (LttFacility*)g_ptr_array_index(t->facilities, j);
963b5f2d 616 for(i=0; i<f->event_number; i++){
617 et = f->events[i];
40331ba8 618 setFieldsOffset(NULL, et, NULL, t);
963b5f2d 619 }
620 }
2a74fbf4 621 return 0;
963b5f2d 622}
3aee1200 623#endif //0
6cd62ccf 624
963b5f2d 625/*****************************************************************************
626 *A trace is specified as a pathname to the directory containing all the
627 *associated data (control tracefiles, per cpu tracefiles, event
628 *descriptions...).
629 *
630 *When a trace is closed, all the associated facilities, types and fields
631 *are released as well.
8d1e6362 632 */
633
634
635/****************************************************************************
636 * get_absolute_pathname
803229fa 637 *
8d1e6362 638 * return the unique pathname in the system
639 *
ef35d837 640 * MD : Fixed this function so it uses realpath, dealing well with
641 * forgotten cases (.. were not used correctly before).
803229fa 642 *
963b5f2d 643 ****************************************************************************/
45e14832 644void get_absolute_pathname(const gchar *pathname, gchar * abs_pathname)
9f797243 645{
9f797243 646 abs_pathname[0] = '\0';
803229fa 647
ef35d837 648 if ( realpath (pathname, abs_pathname) != NULL)
649 return;
650 else
651 {
8d1e6362 652 /* error, return the original path unmodified */
ef35d837 653 strcpy(abs_pathname, pathname);
9f797243 654 return;
655 }
ef35d837 656 return;
9f797243 657}
658
3aee1200 659/* Search for something like : .*_.*
660 *
661 * The left side is the name, the right side is the number.
662 */
663
ae3d0f50 664int get_tracefile_name_number(gchar *raw_name,
3aee1200 665 GQuark *name,
ae3d0f50 666 guint *num,
62e4e7bf 667 guint *tid,
668 guint *pgid,
669 guint64 *creation)
6cd62ccf 670{
3aee1200 671 guint raw_name_len = strlen(raw_name);
672 gchar char_name[PATH_MAX];
3aee1200 673 int i;
674 int underscore_pos;
675 long int cpu_num;
676 gchar *endptr;
62e4e7bf 677 gchar *tmpptr;
3aee1200 678
679 for(i=raw_name_len-1;i>=0;i--) {
680 if(raw_name[i] == '_') break;
681 }
ae3d0f50 682 if(i==-1) { /* Either not found or name length is 0 */
62e4e7bf 683 /* This is a userspace tracefile */
684 strncpy(char_name, raw_name, raw_name_len);
685 char_name[raw_name_len] = '\0';
686 *name = g_quark_from_string(char_name);
687 *num = 0; /* unknown cpu */
688 for(i=0;i<raw_name_len;i++) {
689 if(raw_name[i] == '/') {
690 break;
691 }
692 }
693 i++;
694 for(;i<raw_name_len;i++) {
695 if(raw_name[i] == '/') {
696 break;
697 }
698 }
699 i++;
700 for(;i<raw_name_len;i++) {
701 if(raw_name[i] == '-') {
702 break;
703 }
704 }
705 if(i == raw_name_len) return -1;
706 i++;
707 tmpptr = &raw_name[i];
708 for(;i<raw_name_len;i++) {
709 if(raw_name[i] == '.') {
710 raw_name[i] = ' ';
711 break;
712 }
713 }
714 *tid = strtoul(tmpptr, &endptr, 10);
715 if(endptr == tmpptr)
716 return -1; /* No digit */
717 if(*tid == ULONG_MAX)
718 return -1; /* underflow / overflow */
719 i++;
720 tmpptr = &raw_name[i];
721 for(;i<raw_name_len;i++) {
722 if(raw_name[i] == '.') {
723 raw_name[i] = ' ';
724 break;
725 }
726 }
727 *pgid = strtoul(tmpptr, &endptr, 10);
728 if(endptr == tmpptr)
729 return -1; /* No digit */
730 if(*pgid == ULONG_MAX)
731 return -1; /* underflow / overflow */
732 i++;
733 tmpptr = &raw_name[i];
734 *creation = strtoull(tmpptr, &endptr, 10);
735 if(endptr == tmpptr)
736 return -1; /* No digit */
737 if(*creation == G_MAXUINT64)
738 return -1; /* underflow / overflow */
739 } else {
740 underscore_pos = i;
741
742 cpu_num = strtol(raw_name+underscore_pos+1, &endptr, 10);
743
744 if(endptr == raw_name+underscore_pos+1)
745 return -1; /* No digit */
746 if(cpu_num == LONG_MIN || cpu_num == LONG_MAX)
747 return -1; /* underflow / overflow */
748
749 strncpy(char_name, raw_name, underscore_pos);
750 char_name[underscore_pos] = '\0';
751
752 *name = g_quark_from_string(char_name);
753 *num = cpu_num;
754 }
69bd59ed 755
b333a76b 756
3aee1200 757 return 0;
758}
963b5f2d 759
3aee1200 760
3865ea09 761GData **ltt_trace_get_tracefiles_groups(LttTrace *trace)
77175651 762{
3865ea09 763 return &trace->tracefiles;
77175651 764}
765
766
3865ea09 767void compute_tracefile_group(GQuark key_id,
768 GArray *group,
769 struct compute_tracefile_group_args *args)
77175651 770{
771 int i;
772 LttTracefile *tf;
773
774 for(i=0; i<group->len; i++) {
775 tf = &g_array_index (group, LttTracefile, i);
776 if(tf->cpu_online)
3865ea09 777 args->func(tf, args->func_args);
77175651 778 }
779}
780
781
3aee1200 782void ltt_tracefile_group_destroy(gpointer data)
783{
784 GArray *group = (GArray *)data;
785 int i;
786 LttTracefile *tf;
787
788 for(i=0; i<group->len; i++) {
789 tf = &g_array_index (group, LttTracefile, i);
790 if(tf->cpu_online)
791 ltt_tracefile_close(tf);
792 }
793 g_array_free(group, TRUE);
6cd62ccf 794}
795
3aee1200 796gboolean ltt_tracefile_group_has_cpu_online(gpointer data)
49bf71b5 797{
3aee1200 798 GArray *group = (GArray *)data;
799 int i;
800 LttTracefile *tf;
801
802 for(i=0; i<group->len; i++) {
803 tf = &g_array_index (group, LttTracefile, i);
3c165eaf 804 if(tf->cpu_online)
805 return 1;
3aee1200 806 }
807 return 0;
49bf71b5 808}
809
810
3aee1200 811/* Open each tracefile under a specific directory. Put them in a
812 * GData : permits to access them using their tracefile group pathname.
813 * i.e. access control/modules tracefile group by index :
814 * "control/module".
3865ea09 815 *
816 * relative path is the path relative to the trace root
817 * root path is the full path
3aee1200 818 *
4a55f63e 819 * A tracefile group is simply an array where all the per cpu tracefiles sit.
3aee1200 820 */
821
3c165eaf 822int open_tracefiles(LttTrace *trace, gchar *root_path, gchar *relative_path)
f7afe191 823{
62e4e7bf 824 DIR *dir = opendir(root_path);
825 struct dirent *entry;
826 struct stat stat_buf;
827 int ret;
3865ea09 828
62e4e7bf 829 gchar path[PATH_MAX];
830 int path_len;
831 gchar *path_ptr;
3aee1200 832
3865ea09 833 int rel_path_len;
69bd59ed 834 gchar rel_path[PATH_MAX];
835 gchar *rel_path_ptr;
cb03932a 836 LttTracefile tmp_tf;
3865ea09 837
62e4e7bf 838 if(dir == NULL) {
839 perror(root_path);
840 return ENOENT;
841 }
3aee1200 842
62e4e7bf 843 strncpy(path, root_path, PATH_MAX-1);
844 path_len = strlen(path);
845 path[path_len] = '/';
846 path_len++;
847 path_ptr = path + path_len;
3aee1200 848
3865ea09 849 strncpy(rel_path, relative_path, PATH_MAX-1);
850 rel_path_len = strlen(rel_path);
851 rel_path[rel_path_len] = '/';
852 rel_path_len++;
853 rel_path_ptr = rel_path + rel_path_len;
854
62e4e7bf 855 while((entry = readdir(dir)) != NULL) {
856
857 if(entry->d_name[0] == '.') continue;
858
859 strncpy(path_ptr, entry->d_name, PATH_MAX - path_len);
860 strncpy(rel_path_ptr, entry->d_name, PATH_MAX - rel_path_len);
861
862 ret = stat(path, &stat_buf);
863 if(ret == -1) {
864 perror(path);
865 continue;
866 }
867
868 g_debug("Tracefile file or directory : %s\n", path);
869
74a588bb 870 if(strcmp(rel_path, "/eventdefs") == 0) continue;
871
62e4e7bf 872 if(S_ISDIR(stat_buf.st_mode)) {
3aee1200 873
62e4e7bf 874 g_debug("Entering subdirectory...\n");
875 ret = open_tracefiles(trace, path, rel_path);
876 if(ret < 0) continue;
877 } else if(S_ISREG(stat_buf.st_mode)) {
878 GQuark name;
ae3d0f50 879 guint num, tid, pgid;
62e4e7bf 880 guint64 creation;
3aee1200 881 GArray *group;
ae3d0f50 882 num = tid = pgid = 0;
62e4e7bf 883 creation = 0;
ae3d0f50 884 if(get_tracefile_name_number(rel_path, &name, &num, &tid, &pgid, &creation))
3aee1200 885 continue; /* invalid name */
3865ea09 886
62e4e7bf 887 g_debug("Opening file.\n");
cb03932a 888 if(ltt_tracefile_open(trace, path, &tmp_tf)) {
889 g_info("Error opening tracefile %s", path);
890
891 continue; /* error opening the tracefile : bad magic number ? */
892 }
893
3865ea09 894 g_debug("Tracefile name is %s and number is %u",
895 g_quark_to_string(name), num);
896
cb03932a 897 tmp_tf.cpu_online = 1;
898 tmp_tf.cpu_num = num;
d3d34f49 899 tmp_tf.name = name;
62e4e7bf 900 tmp_tf.tid = tid;
901 tmp_tf.pgid = pgid;
902 tmp_tf.creation = creation;
d1bb700c 903 if(tmp_tf.name == g_quark_from_string("/compact")
62e4e7bf 904 || tmp_tf.name == g_quark_from_string("/flight-compact"))
905 tmp_tf.compact = 1;
d1bb700c 906 else
62e4e7bf 907 tmp_tf.compact = 0;
3865ea09 908 group = g_datalist_id_get_data(&trace->tracefiles, name);
3aee1200 909 if(group == NULL) {
910 /* Elements are automatically cleared when the array is allocated.
911 * It makes the cpu_online variable set to 0 : cpu offline, by default.
912 */
913 group = g_array_sized_new (FALSE, TRUE, sizeof(LttTracefile), 10);
3865ea09 914 g_datalist_id_set_data_full(&trace->tracefiles, name,
3aee1200 915 group, ltt_tracefile_group_destroy);
916 }
cb03932a 917
3aee1200 918 /* Add the per cpu tracefile to the named group */
919 unsigned int old_len = group->len;
920 if(num+1 > old_len)
921 group = g_array_set_size(group, num+1);
cb03932a 922 g_array_index (group, LttTracefile, num) = tmp_tf;
3aee1200 923
62e4e7bf 924 }
925 }
926
927 closedir(dir);
3aee1200 928
62e4e7bf 929 return 0;
f7afe191 930}
931
3aee1200 932/* ltt_get_facility_description
933 *
29e7c5b3 934 * Opens the file corresponding to the requested facility (identified by fac_id
3aee1200 935 * and checksum).
936 *
937 * The name searched is : %trace root%/eventdefs/facname_checksum.xml
938 *
939 * Returns 0 on success, or 1 on failure.
940 */
3c165eaf 941#if 0
3aee1200 942static int ltt_get_facility_description(LttFacility *f,
943 LttTrace *t,
944 LttTracefile *fac_tf)
6cd62ccf 945{
3aee1200 946 char desc_file_name[PATH_MAX];
947 const gchar *text;
948 guint textlen;
949 gint err;
62e4e7bf 950 gint arch_spec;
951 gint fac_name_len;
3aee1200 952
953 text = g_quark_to_string(t->pathname);
954 textlen = strlen(text);
955
956 if(textlen >= PATH_MAX) goto name_error;
957 strcpy(desc_file_name, text);
958
959 text = "/eventdefs/";
960 textlen+=strlen(text);
961 if(textlen >= PATH_MAX) goto name_error;
962 strcat(desc_file_name, text);
963
964 text = g_quark_to_string(f->name);
62e4e7bf 965 fac_name_len = strlen(text);
f5d7967f 966 textlen+=fac_name_len;
3aee1200 967 if(textlen >= PATH_MAX) goto name_error;
968 strcat(desc_file_name, text);
f5d7967f 969
62e4e7bf 970 /* arch specific facilities are named like this : name_arch */
971 if(fac_name_len+1 < sizeof("_arch"))
972 arch_spec = 0;
973 else {
974 if(!strcmp(&text[fac_name_len+1-sizeof("_arch")], "_arch"))
975 arch_spec = 1;
976 else
977 arch_spec = 0;
978 }
f5d7967f 979
29e7c5b3 980#if 0
3aee1200 981 text = "_";
982 textlen+=strlen(text);
983 if(textlen >= PATH_MAX) goto name_error;
984 strcat(desc_file_name, text);
963b5f2d 985
3aee1200 986 err = snprintf(desc_file_name+textlen, PATH_MAX-textlen-1,
987 "%u", f->checksum);
d2083cab 988 if(err < 0) goto name_error;
3aee1200 989
990 textlen=strlen(desc_file_name);
991
29e7c5b3 992#endif //0
62e4e7bf 993
994 if(arch_spec) {
995 switch(t->arch_type) {
996 case LTT_ARCH_TYPE_I386:
997 text = "_i386";
998 break;
999 case LTT_ARCH_TYPE_PPC:
1000 text = "_ppc";
1001 break;
1002 case LTT_ARCH_TYPE_SH:
1003 text = "_sh";
1004 break;
1005 case LTT_ARCH_TYPE_S390:
1006 text = "_s390";
1007 break;
1008 case LTT_ARCH_TYPE_MIPS:
1009 text = "_mips";
1010 break;
1011 case LTT_ARCH_TYPE_ARM:
1012 text = "_arm";
1013 break;
1014 case LTT_ARCH_TYPE_PPC64:
1015 text = "_ppc64";
1016 break;
1017 case LTT_ARCH_TYPE_X86_64:
1018 text = "_x86_64";
1019 break;
1020 case LTT_ARCH_TYPE_C2:
1021 text = "_c2";
1022 break;
1023 case LTT_ARCH_TYPE_POWERPC:
1024 text = "_powerpc";
1025 break;
1026 default:
1027 g_error("Trace from unsupported architecture.");
1028 }
1029 textlen+=strlen(text);
1030 if(textlen >= PATH_MAX) goto name_error;
1031 strcat(desc_file_name, text);
1032 }
1033
3aee1200 1034 text = ".xml";
1035 textlen+=strlen(text);
1036 if(textlen >= PATH_MAX) goto name_error;
1037 strcat(desc_file_name, text);
29e7c5b3 1038
3aee1200 1039 err = ltt_facility_open(f, t, desc_file_name);
1040 if(err) goto facility_error;
3aee1200 1041
1042 return 0;
1043
1044facility_error:
1045name_error:
1046 return 1;
1047}
1048
1049static void ltt_fac_ids_destroy(gpointer data)
1050{
1051 GArray *fac_ids = (GArray *)data;
963b5f2d 1052
3aee1200 1053 g_array_free(fac_ids, TRUE);
1054}
3c165eaf 1055#endif //0
3aee1200 1056
1057/* Presumes the tracefile is already seeked at the beginning. It makes sense,
1058 * because it must be done just after the opening */
3c165eaf 1059int ltt_process_facility_tracefile(LttTracefile *tf)
3aee1200 1060{
1061 int err;
29af7cfd 1062 //LttFacility *fac;
1063 //GArray *fac_ids;
cb03932a 1064 guint i;
29af7cfd 1065 //LttEventType *et;
3aee1200 1066
1067 while(1) {
1068 err = ltt_tracefile_read_seek(tf);
1069 if(err == EPERM) goto seek_error;
1070 else if(err == ERANGE) break; /* End of tracefile */
1071
1072 err = ltt_tracefile_read_update_event(tf);
1073 if(err) goto update_error;
1074
1075 /* We are on a facility load/or facility unload/ or heartbeat event */
1076 /* The rules are :
1077 * * facility 0 is hardcoded : this is the core facility. It will be shown
1078 * in the facility array though, and is shown as "loaded builtin" in the
1079 * trace.
1080 * It contains event :
1081 * 0 : facility load
1082 * 1 : facility unload
1083 * 2 : state dump facility load
d2083cab 1084 * 3 : heartbeat
3aee1200 1085 */
3c165eaf 1086 if(tf->event.event_id >= MARKER_CORE_IDS) {
d2083cab 1087 /* Should only contain core facility */
3aee1200 1088 g_warning("Error in processing facility file %s, "
3c165eaf 1089 "should not contain event id %u.", g_quark_to_string(tf->name),
1090 tf->event.event_id);
3aee1200 1091 err = EPERM;
3c165eaf 1092 goto event_id_error;
d2083cab 1093 } else {
3aee1200 1094
2e13d6af 1095 char *pos;
3c165eaf 1096 const char *marker_name, *format;
1097 uint16_t id;
1098 guint8 int_size, long_size, pointer_size, size_t_size, alignment;
3aee1200 1099
1100 // FIXME align
3c165eaf 1101 switch((enum marker_id)tf->event.event_id) {
1102 case MARKER_ID_SET_MARKER_ID:
2e13d6af 1103 marker_name = pos = tf->event.data;
3c165eaf 1104 g_debug("Doing MARKER_ID_SET_MARKER_ID of marker %s", marker_name);
2e13d6af 1105 pos += strlen(marker_name) + 1;
1106 //remove genevent compatibility
256a5b3a 1107 //pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->alignment);
1108 pos += ltt_align((size_t)pos, sizeof(uint16_t), tf->alignment);
3c165eaf 1109 id = ltt_get_uint16(LTT_GET_BO(tf), pos);
1110 pos += sizeof(guint16);
1111 int_size = *(guint8*)pos;
1112 pos += sizeof(guint8);
1113 long_size = *(guint8*)pos;
1114 pos += sizeof(guint8);
1115 pointer_size = *(guint8*)pos;
1116 pos += sizeof(guint8);
1117 size_t_size = *(guint8*)pos;
1118 pos += sizeof(guint8);
1119 alignment = *(guint8*)pos;
1120 pos += sizeof(guint8);
1121 marker_id_event(tf->trace, g_quark_from_string(marker_name),
1122 id, int_size, long_size,
1123 pointer_size, size_t_size, alignment);
3aee1200 1124 break;
3c165eaf 1125 case MARKER_ID_SET_MARKER_FORMAT:
2e13d6af 1126 marker_name = pos = tf->event.data;
3c165eaf 1127 g_debug("Doing MARKER_ID_SET_MARKER_FORMAT of marker %s",
1128 marker_name);
2e13d6af 1129 pos += strlen(marker_name) + 1;
1130 //break genevent.
256a5b3a 1131 //pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->alignment);
2e13d6af 1132 format = pos;
3c165eaf 1133 pos += strlen(format) + 1;
2e13d6af 1134 //break genevent
256a5b3a 1135 //pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->alignment);
3c165eaf 1136 marker_format_event(tf->trace, g_quark_from_string(marker_name),
1137 format);
1138 /* get information from dictionnary TODO */
3aee1200 1139 break;
3c165eaf 1140 case MARKER_ID_HEARTBEAT_32:
1141 case MARKER_ID_HEARTBEAT_64:
d1bb700c 1142 break;
3aee1200 1143 default:
1144 g_warning("Error in processing facility file %s, "
3c165eaf 1145 "unknown event id %hhu.",
3aee1200 1146 g_quark_to_string(tf->name),
1147 tf->event.event_id);
1148 err = EPERM;
1149 goto event_id_error;
1150 }
1151 }
963b5f2d 1152 }
3aee1200 1153 return 0;
963b5f2d 1154
3aee1200 1155 /* Error handling */
3aee1200 1156event_id_error:
3aee1200 1157update_error:
1158seek_error:
d2083cab 1159 g_warning("An error occured in facility tracefile parsing");
3aee1200 1160 return err;
6cd62ccf 1161}
1162
963b5f2d 1163
3aee1200 1164LttTrace *ltt_trace_open(const gchar *pathname)
1165{
1166 gchar abs_path[PATH_MAX];
1167 LttTrace * t;
1168 LttTracefile *tf;
1169 GArray *group;
b56dcdf2 1170 int i, ret;
16fcbb80 1171 struct ltt_block_start_header *header;
62e4e7bf 1172 DIR *dir;
1173 struct dirent *entry;
b56dcdf2 1174 guint control_found = 0;
1175 guint eventdefs_found = 0;
62e4e7bf 1176 struct stat stat_buf;
b56dcdf2 1177 gchar path[PATH_MAX];
3aee1200 1178
1179 t = g_new(LttTrace, 1);
1180 if(!t) goto alloc_error;
1181
1182 get_absolute_pathname(pathname, abs_path);
1183 t->pathname = g_quark_from_string(abs_path);
1184
3aee1200 1185 g_datalist_init(&t->tracefiles);
b56dcdf2 1186
1187 /* Test to see if it looks like a trace */
62e4e7bf 1188 dir = opendir(abs_path);
1189 if(dir == NULL) {
1190 perror(abs_path);
1191 goto open_error;
1192 }
1193 while((entry = readdir(dir)) != NULL) {
b56dcdf2 1194 strcpy(path, abs_path);
1195 strcat(path, "/");
1196 strcat(path, entry->d_name);
62e4e7bf 1197 ret = stat(path, &stat_buf);
1198 if(ret == -1) {
1199 perror(path);
1200 continue;
1201 }
1202 if(S_ISDIR(stat_buf.st_mode)) {
b56dcdf2 1203 if(strcmp(entry->d_name, "control") == 0) {
1204 control_found = 1;
1205 }
1206 if(strcmp(entry->d_name, "eventdefs") == 0) {
1207 eventdefs_found = 1;
1208 }
1209 }
1210 }
1211 closedir(dir);
1212
1213 if(!control_found || !eventdefs_found) goto find_error;
1214
1215 /* Open all the tracefiles */
e45551ac 1216 if(open_tracefiles(t, abs_path, "")) {
1217 g_warning("Error opening tracefile %s", abs_path);
b56dcdf2 1218 goto find_error;
e45551ac 1219 }
3aee1200 1220
3aee1200 1221 /* Parse each trace control/facilitiesN files : get runtime fac. info */
1222 group = g_datalist_id_get_data(&t->tracefiles, LTT_TRACEFILE_NAME_FACILITIES);
1223 if(group == NULL) {
1224 g_error("Trace %s has no facility tracefile", abs_path);
3865ea09 1225 g_assert(0);
3aee1200 1226 goto facilities_error;
1227 }
1228
16fcbb80 1229 /* Get the trace information for the control/facility 0 tracefile */
1230 g_assert(group->len > 0);
1231 tf = &g_array_index (group, LttTracefile, 0);
1232 header = (struct ltt_block_start_header*)tf->buffer.head;
51551c6f 1233 g_assert(parse_trace_header(header->trace,
1234 tf, t) == 0);
b56dcdf2 1235
1236 t->num_cpu = group->len;
16fcbb80 1237
d79909d1 1238 ret = allocate_marker_data(t);
b44ba972 1239 if (ret)
d79909d1 1240 g_error("Error in allocating marker data");
1241
3aee1200 1242 for(i=0; i<group->len; i++) {
1243 tf = &g_array_index (group, LttTracefile, i);
1244 if(ltt_process_facility_tracefile(tf))
1245 goto facilities_error;
1246 }
dd3a6d39 1247
3aee1200 1248 return t;
1249
1250 /* Error handling */
1251facilities_error:
d79909d1 1252 destroy_marker_data(t);
b56dcdf2 1253find_error:
3aee1200 1254 g_datalist_clear(&t->tracefiles);
b56dcdf2 1255open_error:
3aee1200 1256 g_free(t);
1257alloc_error:
1258 return NULL;
1259
1260}
6cd62ccf 1261
826f1ab2 1262GQuark ltt_trace_name(const LttTrace *t)
6cd62ccf 1263{
3aee1200 1264 return t->pathname;
6cd62ccf 1265}
1266
6cd62ccf 1267
3aee1200 1268/******************************************************************************
1269 * When we copy a trace, we want all the opening actions to happen again :
1270 * the trace will be reopened and totally independant from the original.
1271 * That's why we call ltt_trace_open.
1272 *****************************************************************************/
1273LttTrace *ltt_trace_copy(LttTrace *self)
963b5f2d 1274{
3aee1200 1275 return ltt_trace_open(g_quark_to_string(self->pathname));
963b5f2d 1276}
1277
3aee1200 1278void ltt_trace_close(LttTrace *t)
6cd62ccf 1279{
3aee1200 1280 g_datalist_clear(&t->tracefiles);
1281 g_free(t);
6cd62ccf 1282}
1283
3aee1200 1284
6cd62ccf 1285/*****************************************************************************
3aee1200 1286 *Get the system description of the trace
6cd62ccf 1287 ****************************************************************************/
3c165eaf 1288#if 0
3aee1200 1289LttFacility *ltt_trace_facility_by_id(LttTrace *t, guint8 id)
6cd62ccf 1290{
3aee1200 1291 g_assert(id < t->facilities_by_num->len);
1292 return &g_array_index(t->facilities_by_num, LttFacility, id);
1293}
1294
1295/* ltt_trace_facility_get_by_name
1296 *
1297 * Returns the GArray of facility indexes. All the fac_ids that matches the
1298 * requested facility name.
1299 *
1300 * If name is not found, returns NULL.
1301 */
1302GArray *ltt_trace_facility_get_by_name(LttTrace *t, GQuark name)
1303{
1304 return g_datalist_id_get_data(&t->facilities_by_name, name);
6cd62ccf 1305}
3c165eaf 1306#endif //0
6cd62ccf 1307
1308/*****************************************************************************
963b5f2d 1309 * Functions to discover all the event types in the trace
6cd62ccf 1310 ****************************************************************************/
1311
3aee1200 1312#if 0
963b5f2d 1313unsigned ltt_trace_eventtype_number(LttTrace *t)
6cd62ccf 1314{
8d1e6362 1315 unsigned int i;
963b5f2d 1316 unsigned count = 0;
dc1cad90 1317 unsigned int num = t->facility_number;
963b5f2d 1318 LttFacility * f;
dc1cad90 1319
1320 for(i=0;i<num;i++){
963b5f2d 1321 f = (LttFacility*)g_ptr_array_index(t->facilities, i);
1322 count += f->event_number;
1323 }
1324 return count;
6cd62ccf 1325}
3aee1200 1326#endif //0
6cd62ccf 1327
3aee1200 1328#if 0
1329//use an iteration on all the trace facilities, and inside iteration on all the
1330//event types in each facilities instead.
963b5f2d 1331LttEventType *ltt_trace_eventtype_get(LttTrace *t, unsigned evId)
6cd62ccf 1332{
6e8c19d4 1333 LttEventType *event_type;
1334
963b5f2d 1335 LttFacility * f;
1336 f = ltt_trace_facility_by_id(t,evId);
6e8c19d4 1337
1338 if(unlikely(!f)) event_type = NULL;
1339 else event_type = f->events[evId - f->base_id];
1340
1341 return event_type;
6cd62ccf 1342}
3aee1200 1343#endif //0
6cd62ccf 1344
3aee1200 1345#if 0
6cd62ccf 1346/*****************************************************************************
3aee1200 1347 * ltt_trace_find_tracefile
1348 *
1349 * Find a tracefile by name and index in the group.
1350 *
1351 * Returns a pointer to the tracefiles, else NULL.
6cd62ccf 1352 ****************************************************************************/
6cd62ccf 1353
3aee1200 1354LttTracefile *ltt_trace_find_tracefile(LttTrace *t, const gchar *name)
6cd62ccf 1355{
6cd62ccf 1356}
3aee1200 1357#endif //0
6cd62ccf 1358
1359/*****************************************************************************
3aee1200 1360 * Get the start time and end time of the trace
6cd62ccf 1361 ****************************************************************************/
1362
3c165eaf 1363void ltt_tracefile_time_span_get(LttTracefile *tf,
3aee1200 1364 LttTime *start, LttTime *end)
6cd62ccf 1365{
3aee1200 1366 int err;
6cd62ccf 1367
3aee1200 1368 err = map_block(tf, 0);
1369 if(unlikely(err)) {
1370 g_error("Can not map block");
1371 *start = ltt_time_infinite;
1372 } else
1373 *start = tf->buffer.begin.timestamp;
1374
1375 err = map_block(tf, tf->num_blocks - 1); /* Last block */
1376 if(unlikely(err)) {
1377 g_error("Can not map block");
1378 *end = ltt_time_zero;
1379 } else
1380 *end = tf->buffer.end.timestamp;
6cd62ccf 1381}
1382
3aee1200 1383struct tracefile_time_span_get_args {
1384 LttTrace *t;
1385 LttTime *start;
1386 LttTime *end;
1387};
963b5f2d 1388
3c165eaf 1389void group_time_span_get(GQuark name, gpointer data, gpointer user_data)
963b5f2d 1390{
3aee1200 1391 struct tracefile_time_span_get_args *args =
1392 (struct tracefile_time_span_get_args*)user_data;
1393
1394 GArray *group = (GArray *)data;
1395 int i;
1396 LttTracefile *tf;
1397 LttTime tmp_start;
1398 LttTime tmp_end;
1399
1400 for(i=0; i<group->len; i++) {
1401 tf = &g_array_index (group, LttTracefile, i);
1402 if(tf->cpu_online) {
1403 ltt_tracefile_time_span_get(tf, &tmp_start, &tmp_end);
1404 if(ltt_time_compare(*args->start, tmp_start)>0) *args->start = tmp_start;
1405 if(ltt_time_compare(*args->end, tmp_end)<0) *args->end = tmp_end;
1406 }
1407 }
6cd62ccf 1408}
1409
487ad181 1410void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end)
1411{
3aee1200 1412 LttTime min_start = ltt_time_infinite;
1413 LttTime max_end = ltt_time_zero;
1414 struct tracefile_time_span_get_args args = { t, &min_start, &max_end };
487ad181 1415
3aee1200 1416 g_datalist_foreach(&t->tracefiles, &group_time_span_get, &args);
1417
1418 if(start != NULL) *start = min_start;
1419 if(end != NULL) *end = max_end;
1420
487ad181 1421}
1422
1423
6cd62ccf 1424/*****************************************************************************
963b5f2d 1425 *Get the name of a tracefile
6cd62ccf 1426 ****************************************************************************/
1427
348c6ba8 1428GQuark ltt_tracefile_name(const LttTracefile *tf)
6cd62ccf 1429{
963b5f2d 1430 return tf->name;
6cd62ccf 1431}
1432
348c6ba8 1433GQuark ltt_tracefile_long_name(const LttTracefile *tf)
1434{
1435 return tf->long_name;
1436}
1437
1438
d3d34f49 1439
ae3d0f50 1440guint ltt_tracefile_cpu(LttTracefile *tf)
d3d34f49 1441{
1442 return tf->cpu_num;
1443}
1444
ae3d0f50 1445guint ltt_tracefile_tid(LttTracefile *tf)
1446{
1447 return tf->tid;
1448}
1449
1450guint ltt_tracefile_pgid(LttTracefile *tf)
1451{
1452 return tf->pgid;
1453}
1454
1455guint64 ltt_tracefile_creation(LttTracefile *tf)
1456{
1457 return tf->creation;
1458}
80da81ad 1459/*****************************************************************************
1460 * Get the number of blocks in the tracefile
1461 ****************************************************************************/
1462
3aee1200 1463guint ltt_tracefile_block_number(LttTracefile *tf)
80da81ad 1464{
3aee1200 1465 return tf->num_blocks;
80da81ad 1466}
1467
caf7a67a 1468
3aee1200 1469/* Seek to the first event in a tracefile that has a time equal or greater than
1470 * the time passed in parameter.
1471 *
1472 * If the time parameter is outside the tracefile time span, seek to the first
27304273 1473 * event or if after, return ERANGE.
3aee1200 1474 *
1475 * If the time parameter is before the first event, we have to seek specially to
1476 * there.
1477 *
27304273 1478 * If the time is after the end of the trace, return ERANGE.
3aee1200 1479 *
1480 * Do a binary search to find the right block, then a sequential search in the
1481 * block to find the event.
1482 *
1483 * In the special case where the time requested fits inside a block that has no
1484 * event corresponding to the requested time, the first event of the next block
1485 * will be seeked.
1486 *
1487 * IMPORTANT NOTE : // FIXME everywhere...
1488 *
1489 * You MUST NOT do a ltt_tracefile_read right after a ltt_tracefile_seek_time :
1490 * you will jump over an event if you do.
1491 *
1492 * Return value : 0 : no error, the tf->event can be used
27304273 1493 * ERANGE : time if after the last event of the trace
3aee1200 1494 * otherwise : this is an error.
1495 *
1496 * */
1497
1498int ltt_tracefile_seek_time(LttTracefile *tf, LttTime time)
1499{
1500 int ret = 0;
1501 int err;
1502 unsigned int block_num, high, low;
1503
1504 /* seek at the beginning of trace */
1505 err = map_block(tf, 0); /* First block */
1506 if(unlikely(err)) {
1507 g_error("Can not map block");
1508 goto fail;
caf7a67a 1509 }
1510
3aee1200 1511 /* If the time is lower or equal the beginning of the trace,
1512 * go to the first event. */
1513 if(ltt_time_compare(time, tf->buffer.begin.timestamp) <= 0) {
1514 ret = ltt_tracefile_read(tf);
27304273 1515 if(ret == ERANGE) goto range;
1516 else if (ret) goto fail;
3aee1200 1517 goto found; /* There is either no event in the trace or the event points
1518 to the first event in the trace */
1519 }
caf7a67a 1520
3aee1200 1521 err = map_block(tf, tf->num_blocks - 1); /* Last block */
1522 if(unlikely(err)) {
1523 g_error("Can not map block");
1524 goto fail;
caf7a67a 1525 }
6cd62ccf 1526
27304273 1527 /* If the time is after the end of the trace, return ERANGE. */
1528 if(ltt_time_compare(time, tf->buffer.end.timestamp) > 0) {
1529 goto range;
3aee1200 1530 }
62e55dd6 1531
3aee1200 1532 /* Binary search the block */
1533 high = tf->num_blocks - 1;
1534 low = 0;
1535
1536 while(1) {
1537 block_num = ((high-low) / 2) + low;
1538
1539 err = map_block(tf, block_num);
1540 if(unlikely(err)) {
1541 g_error("Can not map block");
1542 goto fail;
db55eaae 1543 }
3aee1200 1544 if(high == low) {
1545 /* We cannot divide anymore : this is what would happen if the time
1546 * requested was exactly between two consecutive buffers'end and start
1547 * timestamps. This is also what would happend if we didn't deal with out
1548 * of span cases prior in this function. */
1549 /* The event is right in the buffer!
1550 * (or in the next buffer first event) */
1551 while(1) {
1552 ret = ltt_tracefile_read(tf);
27304273 1553 if(ret == ERANGE) goto range; /* ERANGE or EPERM */
3aee1200 1554 else if(ret) goto fail;
1555
d9e13a0f 1556 if(ltt_time_compare(time, tf->event.event_time) <= 0)
e45551ac 1557 goto found;
3aee1200 1558 }
1559
27304273 1560 } else if(ltt_time_compare(time, tf->buffer.begin.timestamp) < 0) {
3aee1200 1561 /* go to lower part */
b1369bef 1562 high = block_num - 1;
3aee1200 1563 } else if(ltt_time_compare(time, tf->buffer.end.timestamp) > 0) {
1564 /* go to higher part */
b1369bef 1565 low = block_num + 1;
3aee1200 1566 } else {/* The event is right in the buffer!
1567 (or in the next buffer first event) */
1568 while(1) {
27304273 1569 ret = ltt_tracefile_read(tf);
1570 if(ret == ERANGE) goto range; /* ERANGE or EPERM */
3aee1200 1571 else if(ret) goto fail;
1572
d9e13a0f 1573 if(ltt_time_compare(time, tf->event.event_time) <= 0)
3aee1200 1574 break;
6cd62ccf 1575 }
3aee1200 1576 goto found;
6cd62ccf 1577 }
6cd62ccf 1578 }
3aee1200 1579
1580found:
1581 return 0;
27304273 1582range:
1583 return ERANGE;
3aee1200 1584
1585 /* Error handling */
1586fail:
1587 g_error("ltt_tracefile_seek_time failed on tracefile %s",
1588 g_quark_to_string(tf->name));
1589 return EPERM;
6cd62ccf 1590}
1591
80da81ad 1592
3aee1200 1593int ltt_tracefile_seek_position(LttTracefile *tf, const LttEventPosition *ep) {
80da81ad 1594
3aee1200 1595 int err;
1596
1597 if(ep->tracefile != tf) {
1598 goto fail;
80da81ad 1599 }
1600
3aee1200 1601 err = map_block(tf, ep->block);
1602 if(unlikely(err)) {
1603 g_error("Can not map block");
1604 goto fail;
1605 }
1606
1607 tf->event.offset = ep->offset;
18206708 1608
62e4e7bf 1609 /* Put back the event real tsc */
1610 tf->event.tsc = ep->tsc;
1611 tf->buffer.tsc = ep->tsc;
78f79181 1612
3aee1200 1613 err = ltt_tracefile_read_update_event(tf);
1614 if(err) goto fail;
1615 err = ltt_tracefile_read_op(tf);
1616 if(err) goto fail;
80da81ad 1617
a0c1f622 1618 return 0;
3aee1200 1619
1620fail:
1621 g_error("ltt_tracefile_seek_time failed on tracefile %s",
1622 g_quark_to_string(tf->name));
a0c1f622 1623 return 1;
3aee1200 1624}
1625
ae3d0f50 1626LttTime ltt_interpolate_time_from_tsc(LttTracefile *tf, guint64 tsc)
3aee1200 1627{
1628 LttTime time;
62e4e7bf 1629
1630 if(tsc > tf->trace->start_tsc) {
1631 time = ltt_time_from_uint64(
1632 (double)(tsc - tf->trace->start_tsc)
1633 * (1000000000.0 / tf->trace->freq_scale)
1634 / (double)tf->trace->start_freq);
1635 time = ltt_time_add(tf->trace->start_time_from_tsc, time);
1636 } else {
1637 time = ltt_time_from_uint64(
1638 (double)(tf->trace->start_tsc - tsc)
1639 * (1000000000.0 / tf->trace->freq_scale)
1640 / (double)tf->trace->start_freq);
1641 time = ltt_time_sub(tf->trace->start_time_from_tsc, time);
1642 }
3aee1200 1643 return time;
80da81ad 1644}
1645
ae3d0f50 1646/* Calculate the real event time based on the buffer boundaries */
1647LttTime ltt_interpolate_time(LttTracefile *tf, LttEvent *event)
1648{
62e4e7bf 1649 return ltt_interpolate_time_from_tsc(tf, tf->buffer.tsc);
ae3d0f50 1650}
1651
eed2ef37 1652
1653/* Get the current event of the tracefile : valid until the next read */
1654LttEvent *ltt_tracefile_get_event(LttTracefile *tf)
1655{
1656 return &tf->event;
1657}
1658
1659
1660
6cd62ccf 1661/*****************************************************************************
1662 *Function name
3aee1200 1663 * ltt_tracefile_read : Read the next event in the tracefile
6cd62ccf 1664 *Input params
1665 * t : tracefile
1666 *Return value
3aee1200 1667 *
1668 * Returns 0 if an event can be used in tf->event.
d822520b 1669 * Returns ERANGE on end of trace. The event in tf->event still can be used
1670 * (if the last block was not empty).
3aee1200 1671 * Returns EPERM on error.
1672 *
1673 * This function does make the tracefile event structure point to the event
1674 * currently pointed to by the tf->event.
1675 *
1676 * Note : you must call a ltt_tracefile_seek to the beginning of the trace to
1677 * reinitialize it after an error if you want results to be coherent.
1678 * It would be the case if a end of trace last buffer has no event : the end
1679 * of trace wouldn't be returned, but an error.
1680 * We make the assumption there is at least one event per buffer.
6cd62ccf 1681 ****************************************************************************/
1682
3aee1200 1683int ltt_tracefile_read(LttTracefile *tf)
6cd62ccf 1684{
963b5f2d 1685 int err;
6cd62ccf 1686
3aee1200 1687 err = ltt_tracefile_read_seek(tf);
1688 if(err) return err;
1689 err = ltt_tracefile_read_update_event(tf);
1690 if(err) return err;
1691 err = ltt_tracefile_read_op(tf);
1692 if(err) return err;
1693
1694 return 0;
1695}
1696
1697int ltt_tracefile_read_seek(LttTracefile *tf)
1698{
1699 int err;
1700
1701 /* Get next buffer until we finally have an event, or end of trace */
1702 while(1) {
1703 err = ltt_seek_next_event(tf);
1704 if(unlikely(err == ENOPROTOOPT)) {
1705 return EPERM;
bdc36259 1706 }
bdc36259 1707
3aee1200 1708 /* Are we at the end of the buffer ? */
1709 if(err == ERANGE) {
1710 if(unlikely(tf->buffer.index == tf->num_blocks-1)){ /* end of trace ? */
1711 return ERANGE;
1712 } else {
1713 /* get next block */
1714 err = map_block(tf, tf->buffer.index + 1);
1715 if(unlikely(err)) {
1716 g_error("Can not map block");
1717 return EPERM;
1718 }
1719 }
1720 } else break; /* We found an event ! */
1721 }
2dee981d 1722
3aee1200 1723 return 0;
1724}
18206708 1725
1726
3aee1200 1727/* do specific operation on events */
1728int ltt_tracefile_read_op(LttTracefile *tf)
1729{
3aee1200 1730 LttEvent *event;
1731
1732 event = &tf->event;
18206708 1733
3aee1200 1734 /* do event specific operation */
40331ba8 1735
3aee1200 1736 /* do something if its an heartbeat event : increment the heartbeat count */
1737 //if(event->facility_id == LTT_FACILITY_CORE)
1738 // if(event->event_id == LTT_EVENT_HEARTBEAT)
1739 // tf->cur_heart_beat_number++;
1740
1741 return 0;
6cd62ccf 1742}
1743
6cd62ccf 1744
3aee1200 1745/* same as ltt_tracefile_read, but does not seek to the next event nor call
1746 * event specific operation. */
1747int ltt_tracefile_read_update_event(LttTracefile *tf)
6cd62ccf 1748{
3aee1200 1749 void * pos;
1750 LttEvent *event;
1751
1752 event = &tf->event;
eed2ef37 1753 pos = tf->buffer.head + event->offset;
3aee1200 1754
1755 /* Read event header */
1756
62e4e7bf 1757 /* Align the head */
1758 if(!tf->compact)
256a5b3a 1759 pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->alignment);
62e4e7bf 1760 else {
1761 g_assert(tf->has_heartbeat);
256a5b3a 1762 pos += ltt_align((size_t)pos, sizeof(uint32_t), tf->alignment);
62e4e7bf 1763 }
3aee1200 1764
62e4e7bf 1765 if(tf->has_heartbeat) {
1766 event->timestamp = ltt_get_uint32(LTT_GET_BO(tf),
1767 pos);
d1bb700c 1768 if(!tf->compact) {
1769 /* 32 bits -> 64 bits tsc */
1770 /* note : still works for seek and non seek cases. */
1771 if(event->timestamp < (0xFFFFFFFFULL&tf->buffer.tsc)) {
1772 tf->buffer.tsc = ((tf->buffer.tsc&0xFFFFFFFF00000000ULL)
1773 + 0x100000000ULL)
1774 | (guint64)event->timestamp;
1775 event->tsc = tf->buffer.tsc;
1776 } else {
1777 /* no overflow */
1778 tf->buffer.tsc = (tf->buffer.tsc&0xFFFFFFFF00000000ULL)
1779 | (guint64)event->timestamp;
1780 event->tsc = tf->buffer.tsc;
62e4e7bf 1781 event->compact_data = 0;
d1bb700c 1782 }
1783 } else {
1784 /* Compact header */
1785 /* We keep the LSB of the previous timestamp, to make sure
1786 * we never go back */
1787 event->event_id = event->timestamp >> tf->tscbits;
dd3a6d39 1788 event->event_id = event->event_id & ((1 << tf->trace->compact_event_bits) - 1);
1789 event->compact_data = event->timestamp >>
62e4e7bf 1790 (tf->trace->compact_event_bits + tf->tscbits);
dd3a6d39 1791 //printf("tsc bits %u, ev bits %u init data %u\n",
62e4e7bf 1792 // tf->tscbits, tf->trace->compact_event_bits, event->compact_data);
dd3a6d39 1793 /* Put the compact data back in original endianness */
1794 event->compact_data = ltt_get_uint32(LTT_GET_BO(tf), &event->compact_data);
d1bb700c 1795 event->event_size = 0xFFFF;
dd3a6d39 1796 //printf("Found compact event %d\n", event->event_id);
1797 //printf("Compact data %d\n", event->compact_data);
d1bb700c 1798 event->timestamp = event->timestamp << tf->tsc_lsb_truncate;
1799 event->timestamp = event->timestamp & tf->tsc_mask;
dd3a6d39 1800 //printf("timestamp 0x%lX\n", event->timestamp);
1801 //printf("mask 0x%llX\n", tf->tsc_mask);
1802 //printf("mask_next 0x%llX\n", tf->tsc_mask_next_bit);
1803 //printf("previous tsc 0x%llX\n", tf->buffer.tsc);
1804 //printf("previous tsc&mask 0x%llX\n", tf->tsc_mask&tf->buffer.tsc);
1805 //printf("previous tsc&(~mask) 0x%llX\n", tf->buffer.tsc&(~tf->tsc_mask));
d1bb700c 1806 if(event->timestamp < (tf->tsc_mask&tf->buffer.tsc)) {
dd3a6d39 1807 //printf("wrap\n");
d1bb700c 1808 tf->buffer.tsc = ((tf->buffer.tsc&(~tf->tsc_mask))
1809 + tf->tsc_mask_next_bit)
1810 | (guint64)event->timestamp;
1811 event->tsc = tf->buffer.tsc;
1812 } else {
dd3a6d39 1813 //printf("no wrap\n");
d1bb700c 1814 /* no overflow */
1815 tf->buffer.tsc = (tf->buffer.tsc&(~tf->tsc_mask))
1816 | (guint64)event->timestamp;
1817 event->tsc = tf->buffer.tsc;
1818 }
dd3a6d39 1819 //printf("current tsc 0x%llX\n", tf->buffer.tsc);
d1bb700c 1820 }
62e4e7bf 1821 pos += sizeof(guint32);
1822 } else {
1823 event->tsc = ltt_get_uint64(LTT_GET_BO(tf), pos);
1824 tf->buffer.tsc = event->tsc;
1825 event->compact_data = 0;
1826 pos += sizeof(guint64);
1827 }
1828 event->event_time = ltt_interpolate_time(tf, event);
3aee1200 1829
d1bb700c 1830 if(!tf->compact) {
3c165eaf 1831 event->event_id = *(guint16*)pos;
1832 pos += sizeof(guint16);
d1bb700c 1833
1834 event->event_size = ltt_get_uint16(LTT_GET_BO(tf), pos);
1835 pos += sizeof(guint16);
1836 } else {
1837 /* Compact event */
1838 }
62e4e7bf 1839 /* Align the head */
1840 if(!tf->compact)
256a5b3a 1841 pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->alignment);
f104d082 1842
3aee1200 1843 event->data = pos;
1844
77175651 1845 /* get the data size and update the event fields with the current
d1bb700c 1846 * information. Also update the time if a heartbeat_full event is found. */
eed2ef37 1847 ltt_update_event_size(tf);
77175651 1848
3aee1200 1849 return 0;
6cd62ccf 1850}
1851
507915ee 1852
6cd62ccf 1853/****************************************************************************
1854 *Function name
3aee1200 1855 * map_block : map a block from the file
6cd62ccf 1856 *Input Params
1857 * lttdes : ltt trace file
1858 * whichBlock : the block which will be read
1859 *return value
1860 * 0 : success
1861 * EINVAL : lseek fail
1862 * EIO : can not read from the file
1863 ****************************************************************************/
1864
3c165eaf 1865gint map_block(LttTracefile * tf, guint block_num)
6cd62ccf 1866{
b77d1b57 1867 int page_size = getpagesize();
3aee1200 1868 struct ltt_block_start_header *header;
1869
1870 g_assert(block_num < tf->num_blocks);
6cd62ccf 1871
f628823c 1872 if(tf->buffer.head != NULL) {
1873 if(munmap(tf->buffer.head, PAGE_ALIGN(tf->buf_size))) {
1874 g_warning("unmap size : %u\n",
1875 PAGE_ALIGN(tf->buf_size));
1876 perror("munmap error");
1877 g_assert(0);
1878 }
1879 }
1880
ac849774 1881
3aee1200 1882 /* Multiple of pages aligned head */
b77d1b57 1883 tf->buffer.head = mmap(0,
f628823c 1884 PAGE_ALIGN(tf->buf_size),
b77d1b57 1885 PROT_READ, MAP_PRIVATE, tf->fd,
f628823c 1886 PAGE_ALIGN((off_t)tf->buf_size * (off_t)block_num));
3aee1200 1887
3865ea09 1888 if(tf->buffer.head == MAP_FAILED) {
3aee1200 1889 perror("Error in allocating memory for buffer of tracefile");
3865ea09 1890 g_assert(0);
3aee1200 1891 goto map_error;
6cd62ccf 1892 }
3865ea09 1893 g_assert( ( (guint)tf->buffer.head&(8-1) ) == 0); // make sure it's aligned.
3aee1200 1894
6cd62ccf 1895
3aee1200 1896 tf->buffer.index = block_num;
1897
1898 header = (struct ltt_block_start_header*)tf->buffer.head;
1899
791dffa6 1900#if 0
986e2a7c 1901 tf->buffer.begin.timestamp = ltt_time_add(
1902 ltt_time_from_uint64(
1903 ltt_get_uint64(LTT_GET_BO(tf),
1904 &header->begin.timestamp)
1905 - tf->trace->start_monotonic),
1906 tf->trace->start_time);
791dffa6 1907#endif //0
348c6ba8 1908 //g_debug("block %u begin : %lu.%lu", block_num,
1909 // tf->buffer.begin.timestamp.tv_sec, tf->buffer.begin.timestamp.tv_nsec);
3aee1200 1910 tf->buffer.begin.cycle_count = ltt_get_uint64(LTT_GET_BO(tf),
1911 &header->begin.cycle_count);
986e2a7c 1912 tf->buffer.begin.freq = ltt_get_uint64(LTT_GET_BO(tf),
1913 &header->begin.freq);
62e4e7bf 1914 if(tf->buffer.begin.freq == 0)
1915 tf->buffer.begin.freq = tf->trace->start_freq;
ae3d0f50 1916
1917 tf->buffer.begin.timestamp = ltt_interpolate_time_from_tsc(tf,
62e4e7bf 1918 tf->buffer.begin.cycle_count);
ae3d0f50 1919#if 0
62e4e7bf 1920 ltt_time_add(
791dffa6 1921 ltt_time_from_uint64(
88612d17 1922 (double)(tf->buffer.begin.cycle_count
1923 - tf->trace->start_tsc) * 1000000.0
791dffa6 1924 / (double)tf->trace->start_freq),
62e4e7bf 1925 tf->trace->start_time_from_tsc);
ae3d0f50 1926#endif //0
791dffa6 1927#if 0
1928
986e2a7c 1929 tf->buffer.end.timestamp = ltt_time_add(
1930 ltt_time_from_uint64(
1931 ltt_get_uint64(LTT_GET_BO(tf),
1932 &header->end.timestamp)
1933 - tf->trace->start_monotonic),
1934 tf->trace->start_time);
791dffa6 1935#endif //0
348c6ba8 1936 //g_debug("block %u end : %lu.%lu", block_num,
1937 // tf->buffer.end.timestamp.tv_sec, tf->buffer.end.timestamp.tv_nsec);
3aee1200 1938 tf->buffer.end.cycle_count = ltt_get_uint64(LTT_GET_BO(tf),
1939 &header->end.cycle_count);
986e2a7c 1940 tf->buffer.end.freq = ltt_get_uint64(LTT_GET_BO(tf),
1941 &header->end.freq);
62e4e7bf 1942 if(tf->buffer.end.freq == 0)
1943 tf->buffer.end.freq = tf->trace->start_freq;
1944
3aee1200 1945 tf->buffer.lost_size = ltt_get_uint32(LTT_GET_BO(tf),
986e2a7c 1946 &header->lost_size);
ae3d0f50 1947 tf->buffer.end.timestamp = ltt_interpolate_time_from_tsc(tf,
62e4e7bf 1948 tf->buffer.end.cycle_count);
ae3d0f50 1949#if 0
62e4e7bf 1950 ltt_time_add(
791dffa6 1951 ltt_time_from_uint64(
88612d17 1952 (double)(tf->buffer.end.cycle_count
1953 - tf->trace->start_tsc) * 1000000.0
791dffa6 1954 / (double)tf->trace->start_freq),
88612d17 1955 tf->trace->start_time_from_tsc);
ae3d0f50 1956#endif //0
3aee1200 1957 tf->buffer.tsc = tf->buffer.begin.cycle_count;
1958 tf->event.tsc = tf->buffer.tsc;
986e2a7c 1959 tf->buffer.freq = tf->buffer.begin.freq;
3aee1200 1960
1961 /* FIXME
1962 * eventually support variable buffer size : will need a partial pre-read of
1963 * the headers to create an index when we open the trace... eventually. */
f628823c 1964 g_assert(tf->buf_size == ltt_get_uint32(LTT_GET_BO(tf),
3aee1200 1965 &header->buf_size));
507915ee 1966
3aee1200 1967 /* Now that the buffer is mapped, calculate the time interpolation for the
1968 * block. */
1969
791dffa6 1970// tf->buffer.nsecs_per_cycle = calc_nsecs_per_cycle(tf);
1971 //tf->buffer.cyc2ns_scale = calc_nsecs_per_cycle(tf);
3aee1200 1972
1973 /* Make the current event point to the beginning of the buffer :
1974 * it means that the event read must get the first event. */
1975 tf->event.tracefile = tf;
1976 tf->event.block = block_num;
eed2ef37 1977 tf->event.offset = 0;
3aee1200 1978
1979 return 0;
6cd62ccf 1980
3aee1200 1981map_error:
1982 return -errno;
40331ba8 1983
6cd62ccf 1984}
1985
77175651 1986/* It will update the fields offsets too */
1987void ltt_update_event_size(LttTracefile *tf)
6cd62ccf 1988{
2312de30 1989 off_t size = 0;
d1bb700c 1990 char *tscdata;
d2007fbd 1991 struct marker_info *info;
44f317b7 1992
d2007fbd 1993 switch((enum marker_id)tf->event.event_id) {
1994 case MARKER_ID_SET_MARKER_ID:
44f317b7 1995 size = strlen((char*)tf->event.data) + 1;
d2007fbd 1996 //g_debug("marker %s id set", (char*)tf->event.data);
256a5b3a 1997 size += ltt_align(size, sizeof(guint16), tf->alignment);
d2007fbd 1998 size += sizeof(guint16);
3c165eaf 1999 size += sizeof(guint8);
2000 size += sizeof(guint8);
2001 size += sizeof(guint8);
2002 size += sizeof(guint8);
2003 size += sizeof(guint8);
44f317b7 2004 break;
d2007fbd 2005 case MARKER_ID_SET_MARKER_FORMAT:
2006 //g_debug("marker %s format set", (char*)tf->event.data);
44f317b7 2007 size = strlen((char*)tf->event.data) + 1;
2e13d6af 2008 size += strlen((char*)tf->event.data + size) + 1;
44f317b7 2009 break;
d2007fbd 2010 case MARKER_ID_HEARTBEAT_32:
2011 //g_debug("Update Event heartbeat 32 bits");
44f317b7 2012 break;
d2007fbd 2013 case MARKER_ID_HEARTBEAT_64:
2014 //g_debug("Update Event heartbeat 64 bits");
d1bb700c 2015 tscdata = (char*)(tf->event.data);
2016 tf->event.tsc = ltt_get_uint64(LTT_GET_BO(tf), tscdata);
2017 tf->buffer.tsc = tf->event.tsc;
2018 tf->event.event_time = ltt_interpolate_time(tf, &tf->event);
256a5b3a 2019 size = ltt_align(size, sizeof(guint64), tf->alignment);
d2007fbd 2020 size += sizeof(guint64);
d1bb700c 2021 break;
256a5b3a 2022 }
2023
2024 info = marker_get_info_from_id(tf->trace, tf->event.event_id);
2025 if (tf->event.event_id >= MARKER_CORE_IDS)
2026 g_assert(info != NULL);
2027
2028 /* Do not update field offsets of core markers when initially reading the
2029 * facility tracefile when the infos about these markers do not exist yet.
2030 */
2031 if (likely(info && info->fields)) {
2032 if (info->size != -1)
2033 size = info->size;
2034 else
2035 size = marker_update_fields_offsets(marker_get_info_from_id(tf->trace,
2036 tf->event.event_id), tf->event.data);
44f317b7 2037 }
c4afd5d8 2038
d2007fbd 2039 tf->event.data_size = size;
2040
2041 /* Check consistency between kernel and LTTV structure sizes */
2042 if(tf->event.event_size == 0xFFFF) {
2043 /* Event size too big to fit in the event size field */
2044 tf->event.event_size = tf->event.data_size;
2045 }
2046 if (tf->event.data_size != tf->event.event_size) {
3c165eaf 2047 struct marker_info *info = marker_get_info_from_id(tf->trace,
2048 tf->event.event_id);
2049 g_error("Kernel/LTTV event size differs for event %s: kernel %u, LTTV %u",
2050 g_quark_to_string(info->name),
2051 tf->event.event_size, tf->event.data_size);
d2007fbd 2052 exit(-1);
2053 }
2054
2055#if 0
44f317b7 2056 LttEventType *event_type =
2057 ltt_facility_eventtype_get(f, tf->event.event_id);
c4afd5d8 2058
44f317b7 2059 if(!event_type) {
2060 g_warning("Unknown event id %hhu in facility %s in tracefile %s",
2061 tf->event.event_id,
2062 g_quark_to_string(f->name),
2063 g_quark_to_string(tf->name));
2064 goto event_type_error;
3aee1200 2065 }
3aee1200 2066
44f317b7 2067 /* Compute the dynamic offsets */
2068 compute_offsets(tf, f, event_type, &size, tf->event.data);
2069
2070 //g_debug("Event root field : f.e %hhu.%hhu size %zd",
2071 // tf->event.facility_id,
2072 // tf->event.event_id, size);
7cbcdb89 2073
2074no_offset:
77175651 2075 tf->event.data_size = size;
eed2ef37 2076
b77d1b57 2077 /* Check consistency between kernel and LTTV structure sizes */
62e4e7bf 2078 if(tf->event.event_size == 0xFFFF) {
2079 /* Event size too big to fit in the event size field */
2080 tf->event.event_size = tf->event.data_size;
2081 }
f63ebe51 2082 if (tf->event.data_size != tf->event.event_size) {
2083 g_error("Kernel/LTTV event size differs for event %s.%s: kernel %u, LTTV %u",
62e4e7bf 2084 g_quark_to_string(f->name), g_quark_to_string(event_type->name),
2085 tf->event.event_size, tf->event.data_size);
f63ebe51 2086 exit(-1);
2087 }
2088 //g_assert(tf->event.data_size == tf->event.event_size);
9eb6aa7a 2089
eed2ef37 2090 return;
2091
c4afd5d8 2092event_type_error:
3aee1200 2093event_id_error:
62e4e7bf 2094 if(tf->event.event_size == 0xFFFF) {
2095 g_error("Cannot jump over an unknown event bigger than 0xFFFE bytes");
2096 }
2097 /* The facility is unknown : use the kernel information about this event
2098 * to jump over it. */
9d7e0c25 2099 tf->event.data_size = tf->event.event_size;
d2007fbd 2100#endif //0
6cd62ccf 2101}
2102
6cd62ccf 2103
3aee1200 2104/* Take the tf current event offset and use the event facility id and event id
2105 * to figure out where is the next event offset.
2106 *
2107 * This is an internal function not aiming at being used elsewhere : it will
2108 * not jump over the current block limits. Please consider using
2109 * ltt_tracefile_read to do this.
2110 *
2111 * Returns 0 on success
2112 * ERANGE if we are at the end of the buffer.
2113 * ENOPROTOOPT if an error occured when getting the current event size.
2114 */
3c165eaf 2115int ltt_seek_next_event(LttTracefile *tf)
6cd62ccf 2116{
3aee1200 2117 int ret = 0;
2118 void *pos;
3aee1200 2119
2120 /* seek over the buffer header if we are at the buffer start */
eed2ef37 2121 if(tf->event.offset == 0) {
51551c6f 2122 tf->event.offset += tf->buffer_header_size;
b77d1b57 2123
f628823c 2124 if(tf->event.offset == tf->buf_size - tf->buffer.lost_size) {
b77d1b57 2125 ret = ERANGE;
2126 }
3aee1200 2127 goto found;
2128 }
6cd62ccf 2129
6cd62ccf 2130
3aee1200 2131 pos = tf->event.data;
2132
77175651 2133 if(tf->event.data_size < 0) goto error;
3aee1200 2134
77175651 2135 pos += (size_t)tf->event.data_size;
3aee1200 2136
eed2ef37 2137 tf->event.offset = pos - tf->buffer.head;
cb03932a 2138
f628823c 2139 if(tf->event.offset == tf->buf_size - tf->buffer.lost_size) {
cb03932a 2140 ret = ERANGE;
2141 goto found;
2142 }
36d36c9f 2143 g_assert(tf->event.offset < tf->buf_size - tf->buffer.lost_size);
3aee1200 2144
2145found:
2146 return ret;
2147
2148error:
2149 g_error("Error in ltt_seek_next_event for tracefile %s",
2150 g_quark_to_string(tf->name));
2151 return ENOPROTOOPT;
6cd62ccf 2152}
2153
791dffa6 2154#if 0
6cd62ccf 2155/*****************************************************************************
2156 *Function name
3aee1200 2157 * calc_nsecs_per_cycle : calculate nsecs per cycle for current block
986e2a7c 2158 *
2159 * 1.0 / (freq(khz) *1000) * 1000000000
6cd62ccf 2160 *Input Params
2161 * t : tracefile
2162 ****************************************************************************/
986e2a7c 2163/* from timer_tsc.c */
2164#define CYC2NS_SCALE_FACTOR 10
791dffa6 2165static guint32 calc_nsecs_per_cycle(LttTracefile * tf)
6cd62ccf 2166{
986e2a7c 2167 //return 1e6 / (double)tf->buffer.freq;
791dffa6 2168 guint32 cpu_mhz = tf->buffer.freq / 1000;
2169 guint32 cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz;
6cd62ccf 2170
791dffa6 2171 return cyc2ns_scale;
986e2a7c 2172 // return 1e6 / (double)tf->buffer.freq;
3aee1200 2173}
791dffa6 2174
2175static guint64 cycles_2_ns(LttTracefile *tf, guint64 cycles)
2176{
2177 return (cycles * tf->buffer.cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
2178}
2179#endif //0
2180
3aee1200 2181#if 0
2182void setFieldsOffset(LttTracefile *tf, LttEventType *evT,void *evD)
2183{
2184 LttField * rootFld = evT->root_field;
2185 // rootFld->base_address = evD;
2dee981d 2186
3aee1200 2187 if(likely(rootFld))
2188 rootFld->field_size = getFieldtypeSize(tf, evT->facility,
2189 evT, 0,0,rootFld, evD);
6cd62ccf 2190}
3aee1200 2191#endif //0
f104d082 2192#if 0
3aee1200 2193/*****************************************************************************
6cd62ccf 2194 *Function name
3aee1200 2195 * set_fields_offsets : set the precomputable offset of the fields
6cd62ccf 2196 *Input params
3aee1200 2197 * tracefile : opened trace file
2198 * event_type : the event type
6cd62ccf 2199 ****************************************************************************/
2200
3aee1200 2201void set_fields_offsets(LttTracefile *tf, LttEventType *event_type)
6cd62ccf 2202{
3aee1200 2203 LttField *field = event_type->root_field;
2204 enum field_status fixed_root = FIELD_FIXED, fixed_parent = FIELD_FIXED;
2205
2206 if(likely(field))
2207 preset_field_type_size(tf, event_type, 0, 0,
2208 &fixed_root, &fixed_parent,
2209 field);
2210
2211}
f104d082 2212#endif //0
2213
2214
2215/*****************************************************************************
2216 *Function name
2217 * get_alignment : Get the alignment needed for a field.
2218 *Input params
f104d082 2219 * field : field
2220 *
2221 * returns : The size on which it must be aligned.
2222 *
2223 ****************************************************************************/
3c165eaf 2224#if 0
743e50fd 2225off_t get_alignment(LttField *field)
f104d082 2226{
2312de30 2227 LttType *type = &field->field_type;
f104d082 2228
2229 switch(type->type_class) {
2230 case LTT_INT_FIXED:
2231 case LTT_UINT_FIXED:
2232 case LTT_POINTER:
2233 case LTT_CHAR:
2234 case LTT_UCHAR:
2235 case LTT_SHORT:
2236 case LTT_USHORT:
2237 case LTT_INT:
2238 case LTT_UINT:
2239 case LTT_LONG:
2240 case LTT_ULONG:
2241 case LTT_SIZE_T:
2242 case LTT_SSIZE_T:
2243 case LTT_OFF_T:
2244 case LTT_FLOAT:
2245 case LTT_ENUM:
2246 /* Align offset on type size */
83e160f2 2247 g_assert(field->field_size != 0);
f104d082 2248 return field->field_size;
2249 break;
2250 case LTT_STRING:
83e160f2 2251 return 1;
f104d082 2252 break;
2253 case LTT_ARRAY:
2254 g_assert(type->fields->len == 1);
2255 {
2256 LttField *child = &g_array_index(type->fields, LttField, 0);
743e50fd 2257 return get_alignment(child);
f104d082 2258 }
2259 break;
2260 case LTT_SEQUENCE:
2261 g_assert(type->fields->len == 2);
2262 {
83e160f2 2263 off_t localign = 1;
f104d082 2264 LttField *child = &g_array_index(type->fields, LttField, 0);
2265
743e50fd 2266 localign = max(localign, get_alignment(child));
f104d082 2267
2268 child = &g_array_index(type->fields, LttField, 1);
743e50fd 2269 localign = max(localign, get_alignment(child));
f104d082 2270
2271 return localign;
2272 }
2273 break;
2274 case LTT_STRUCT:
2275 case LTT_UNION:
2276 {
2277 guint i;
83e160f2 2278 off_t localign = 1;
f104d082 2279
2280 for(i=0; i<type->fields->len; i++) {
2281 LttField *child = &g_array_index(type->fields, LttField, i);
743e50fd 2282 localign = max(localign, get_alignment(child));
f104d082 2283 }
2284 return localign;
2285 }
2286 break;
2287 case LTT_NONE:
2288 default:
2289 g_error("get_alignment : unknown type");
83e160f2 2290 return -1;
f104d082 2291 }
f104d082 2292}
2293
3c165eaf 2294#endif //0
2295
f104d082 2296/*****************************************************************************
2297 *Function name
2298 * field_compute_static_size : Determine the size of fields known by their
2299 * sole definition. Unions, arrays and struct sizes might be known, but
2300 * the parser does not give that information.
2301 *Input params
2302 * tf : tracefile
2303 * field : field
2304 *
2305 ****************************************************************************/
3c165eaf 2306#if 0
743e50fd 2307void field_compute_static_size(LttFacility *fac, LttField *field)
f104d082 2308{
2312de30 2309 LttType *type = &field->field_type;
f104d082 2310
2311 switch(type->type_class) {
2312 case LTT_INT_FIXED:
2313 case LTT_UINT_FIXED:
2314 case LTT_POINTER:
2315 case LTT_CHAR:
2316 case LTT_UCHAR:
2317 case LTT_SHORT:
2318 case LTT_USHORT:
2319 case LTT_INT:
2320 case LTT_UINT:
2321 case LTT_LONG:
2322 case LTT_ULONG:
2323 case LTT_SIZE_T:
2324 case LTT_SSIZE_T:
2325 case LTT_OFF_T:
2326 case LTT_FLOAT:
2327 case LTT_ENUM:
2328 case LTT_STRING:
2329 /* nothing to do */
2330 break;
2331 case LTT_ARRAY:
2332 /* note this : array type size is the number of elements in the array,
2333 * while array field size of the length of the array in bytes */
2334 g_assert(type->fields->len == 1);
2335 {
2336 LttField *child = &g_array_index(type->fields, LttField, 0);
743e50fd 2337 field_compute_static_size(fac, child);
f104d082 2338
2339 if(child->field_size != 0) {
2340 field->field_size = type->size * child->field_size;
2341 field->dynamic_offsets = g_array_sized_new(FALSE, TRUE,
2342 sizeof(off_t), type->size);
2343 } else {
2344 field->field_size = 0;
2345 }
2346 }
2347 break;
2348 case LTT_SEQUENCE:
2349 g_assert(type->fields->len == 2);
2350 {
2312de30 2351 off_t local_offset = 0;
f104d082 2352 LttField *child = &g_array_index(type->fields, LttField, 1);
743e50fd 2353 field_compute_static_size(fac, child);
f104d082 2354 field->field_size = 0;
2355 type->size = 0;
2356 if(child->field_size != 0) {
2357 field->dynamic_offsets = g_array_sized_new(FALSE, TRUE,
2358 sizeof(off_t), SEQUENCE_AVG_ELEMENTS);
2359 }
2360 }
2361 break;
2362 case LTT_STRUCT:
2363 case LTT_UNION:
2364 {
2365 guint i;
2366 for(i=0;i<type->fields->len;i++) {
2367 LttField *child = &g_array_index(type->fields, LttField, i);
743e50fd 2368 field_compute_static_size(fac, child);
f104d082 2369 if(child->field_size != 0) {
743e50fd 2370 type->size += ltt_align(type->size, get_alignment(child),
2371 fac->alignment);
f104d082 2372 type->size += child->field_size;
2373 } else {
2374 /* As soon as we find a child with variable size, we have
2375 * a variable size */
2376 type->size = 0;
2377 break;
2378 }
2379 }
2380 field->field_size = type->size;
2381 }
2382 break;
2383 default:
2384 g_error("field_static_size : unknown type");
2312de30 2385 }
f104d082 2386
2387}
3c165eaf 2388#endif //0
f104d082 2389
2390
2391/*****************************************************************************
2392 *Function name
2393 * precompute_fields_offsets : set the precomputable offset of the fields
2394 *Input params
743e50fd 2395 * fac : facility
f104d082 2396 * field : the field
2397 * offset : pointer to the current offset, must be incremented
2398 *
2399 * return : 1 : found a variable length field, stop the processing.
2400 * 0 otherwise.
2401 ****************************************************************************/
2402
3c165eaf 2403#if 0
dd3a6d39 2404gint precompute_fields_offsets(LttFacility *fac, LttField *field, off_t *offset, gint is_compact)
f104d082 2405{
2312de30 2406 LttType *type = &field->field_type;
dd3a6d39 2407
2408 if(unlikely(is_compact)) {
2409 g_assert(field->field_size != 0);
2410 /* FIXME THIS IS A HUUUUUGE hack :
2411 * offset is between the compact_data field in struct LttEvent
2412 * and the address of the field root in the memory map.
2413 * ark. Both will stay at the same addresses while the event
2414 * is readable, so it's ok.
2415 */
2416 field->offset_root = 0;
2417 field->fixed_root = FIELD_FIXED;
2418 return 0;
2419 }
f104d082 2420
2421 switch(type->type_class) {
2422 case LTT_INT_FIXED:
2423 case LTT_UINT_FIXED:
2424 case LTT_POINTER:
2425 case LTT_CHAR:
2426 case LTT_UCHAR:
2427 case LTT_SHORT:
2428 case LTT_USHORT:
2429 case LTT_INT:
2430 case LTT_UINT:
2431 case LTT_LONG:
2432 case LTT_ULONG:
2433 case LTT_SIZE_T:
2434 case LTT_SSIZE_T:
2435 case LTT_OFF_T:
2436 case LTT_FLOAT:
2437 case LTT_ENUM:
743e50fd 2438 g_assert(field->field_size != 0);
f104d082 2439 /* Align offset on type size */
743e50fd 2440 *offset += ltt_align(*offset, get_alignment(field),
2441 fac->alignment);
f104d082 2442 /* remember offset */
2443 field->offset_root = *offset;
2444 field->fixed_root = FIELD_FIXED;
2445 /* Increment offset */
2446 *offset += field->field_size;
2447 return 0;
2448 break;
2449 case LTT_STRING:
2450 field->offset_root = *offset;
2451 field->fixed_root = FIELD_FIXED;
2452 return 1;
2453 break;
2454 case LTT_ARRAY:
2455 g_assert(type->fields->len == 1);
2456 {
2457 LttField *child = &g_array_index(type->fields, LttField, 0);
2458
743e50fd 2459 *offset += ltt_align(*offset, get_alignment(field),
2460 fac->alignment);
f104d082 2461
2462 /* remember offset */
2463 field->offset_root = *offset;
2464 field->array_offset = *offset;
2465 field->fixed_root = FIELD_FIXED;
2466
2467 /* Let the child be variable */
2468 //precompute_fields_offsets(tf, child, offset);
2469
2470 if(field->field_size != 0) {
2471 /* Increment offset */
2472 /* field_size is the array size in bytes */
2473 *offset += field->field_size;
2474 return 0;
2475 } else {
2476 return 1;
2477 }
2478 }
2479 break;
2480 case LTT_SEQUENCE:
2481 g_assert(type->fields->len == 2);
2482 {
2483 LttField *child;
2484 guint ret;
2485
743e50fd 2486 *offset += ltt_align(*offset, get_alignment(field),
2487 fac->alignment);
f104d082 2488
2489 /* remember offset */
2490 field->offset_root = *offset;
2491 field->fixed_root = FIELD_FIXED;
2492
2493 child = &g_array_index(type->fields, LttField, 0);
dd3a6d39 2494 ret = precompute_fields_offsets(fac, child, offset, is_compact);
f104d082 2495 g_assert(ret == 0); /* Seq len cannot have variable len */
2496
2497 child = &g_array_index(type->fields, LttField, 1);
743e50fd 2498 *offset += ltt_align(*offset, get_alignment(child),
2499 fac->alignment);
f104d082 2500 field->array_offset = *offset;
743e50fd 2501 /* Let the child be variable. */
2502 //ret = precompute_fields_offsets(fac, child, offset);
f104d082 2503
2504 /* Cannot precompute fields offsets of sequence members, and has
2505 * variable length. */
2506 return 1;
2507 }
2508 break;
2509 case LTT_STRUCT:
2510 {
2511 LttField *child;
2512 guint i;
2513 gint ret=0;
2514
743e50fd 2515 *offset += ltt_align(*offset, get_alignment(field),
2516 fac->alignment);
f104d082 2517 /* remember offset */
2518 field->offset_root = *offset;
2519 field->fixed_root = FIELD_FIXED;
2520
2521 for(i=0; i< type->fields->len; i++) {
2522 child = &g_array_index(type->fields, LttField, i);
dd3a6d39 2523 ret = precompute_fields_offsets(fac, child, offset, is_compact);
f104d082 2524
2525 if(ret) break;
2526 }
2527 return ret;
2528 }
2529 break;
2530 case LTT_UNION:
2531 {
2532 LttField *child;
2533 guint i;
2534 gint ret=0;
2535
743e50fd 2536 *offset += ltt_align(*offset, get_alignment(field),
2537 fac->alignment);
f104d082 2538 /* remember offset */
2539 field->offset_root = *offset;
2540 field->fixed_root = FIELD_FIXED;
2541
2542 for(i=0; i< type->fields->len; i++) {
2543 *offset = field->offset_root;
2544 child = &g_array_index(type->fields, LttField, i);
dd3a6d39 2545 ret = precompute_fields_offsets(fac, child, offset, is_compact);
f104d082 2546
2547 if(ret) break;
2548 }
2549 *offset = field->offset_root + field->field_size;
2550 return ret;
2551 }
2552
2553 break;
2554 case LTT_NONE:
2555 default:
2556 g_error("precompute_fields_offsets : unknown type");
2557 return 1;
2558 }
2559
2560}
2561
3c165eaf 2562#endif //0
f104d082 2563
3c165eaf 2564#if 0
f104d082 2565/*****************************************************************************
2566 *Function name
2567 * precompute_offsets : set the precomputable offset of an event type
2568 *Input params
2569 * tf : tracefile
2570 * event : event type
2571 *
2572 ****************************************************************************/
743e50fd 2573void precompute_offsets(LttFacility *fac, LttEventType *event)
f104d082 2574{
2575 guint i;
2576 off_t offset = 0;
2577 gint ret;
2578
2579 /* First, compute the size of fixed size fields. Will determine size for
2580 * arrays, struct and unions, which is not done by the parser */
2581 for(i=0; i<event->fields->len; i++) {
2582 LttField *field = &g_array_index(event->fields, LttField, i);
743e50fd 2583 field_compute_static_size(fac, field);
f104d082 2584 }
2585
2586 /* Precompute all known offsets */
2587 for(i=0; i<event->fields->len; i++) {
2588 LttField *field = &g_array_index(event->fields, LttField, i);
dd3a6d39 2589 if(event->has_compact_data && i == 0)
2590 ret = precompute_fields_offsets(fac, field, &offset, 1);
2591 else
2592 ret = precompute_fields_offsets(fac, field, &offset, 0);
f104d082 2593 if(ret) break;
2594 }
2595}
3c165eaf 2596#endif //0
f104d082 2597
e4eced0f 2598
bbf28e50 2599
3aee1200 2600/*****************************************************************************
2601 *Function name
2602 * preset_field_type_size : set the fixed sizes of the field type
2603 *Input params
2604 * tf : tracefile
2605 * event_type : event type
2606 * offset_root : offset from the root
2607 * offset_parent : offset from the parent
2608 * fixed_root : Do we know a fixed offset to the root ?
2609 * fixed_parent : Do we know a fixed offset to the parent ?
2610 * field : field
2611 ****************************************************************************/
f104d082 2612
2613
2614
2615// preset the fixed size offsets. Calculate them just like genevent-new : an
2616// increment of a *to value that represents the offset from the start of the
2617// event data.
2618// The preset information is : offsets up to (and including) the first element
2619// of variable size. All subsequent fields must be flagged "VARIABLE OFFSET".
2620#if 0
3aee1200 2621void preset_field_type_size(LttTracefile *tf, LttEventType *event_type,
2622 off_t offset_root, off_t offset_parent,
2623 enum field_status *fixed_root, enum field_status *fixed_parent,
2624 LttField *field)
2625{
2626 enum field_status local_fixed_root, local_fixed_parent;
2627 guint i;
2628 LttType *type;
dfb73233 2629
3aee1200 2630 g_assert(field->fixed_root == FIELD_UNKNOWN);
2631 g_assert(field->fixed_parent == FIELD_UNKNOWN);
2632 g_assert(field->fixed_size == FIELD_UNKNOWN);
dfb73233 2633
3aee1200 2634 type = field->field_type;
2635
2636 field->fixed_root = *fixed_root;
2637 if(field->fixed_root == FIELD_FIXED)
2638 field->offset_root = offset_root;
2639 else
2640 field->offset_root = 0;
2641
2642 field->fixed_parent = *fixed_parent;
2643 if(field->fixed_parent == FIELD_FIXED)
2644 field->offset_parent = offset_parent;
2645 else
2646 field->offset_parent = 0;
2647
2648 size_t current_root_offset;
2649 size_t current_offset;
2650 enum field_status current_child_status, final_child_status;
2651 size_t max_size;
2652
2653 switch(type->type_class) {
83e160f2 2654 case LTT_INT_FIXED:
2655 case LTT_UINT_FIXED:
2656 case LTT_CHAR:
2657 case LTT_UCHAR:
2658 case LTT_SHORT:
2659 case LTT_USHORT:
3aee1200 2660 case LTT_INT:
2661 case LTT_UINT:
2662 case LTT_FLOAT:
2663 case LTT_ENUM:
2664 field->field_size = ltt_type_size(tf->trace, type);
2665 field->fixed_size = FIELD_FIXED;
2666 break;
2667 case LTT_POINTER:
2668 field->field_size = (off_t)event_type->facility->pointer_size;
2669 field->fixed_size = FIELD_FIXED;
2670 break;
2671 case LTT_LONG:
2672 case LTT_ULONG:
cb03932a 2673 field->field_size = (off_t)event_type->facility->long_size;
3aee1200 2674 field->fixed_size = FIELD_FIXED;
2675 break;
2676 case LTT_SIZE_T:
2677 case LTT_SSIZE_T:
2678 case LTT_OFF_T:
2679 field->field_size = (off_t)event_type->facility->size_t_size;
2680 field->fixed_size = FIELD_FIXED;
2681 break;
2682 case LTT_SEQUENCE:
2683 local_fixed_root = FIELD_VARIABLE;
2684 local_fixed_parent = FIELD_VARIABLE;
2685 preset_field_type_size(tf, event_type,
2686 0, 0,
2687 &local_fixed_root, &local_fixed_parent,
2688 field->child[0]);
2689 field->fixed_size = FIELD_VARIABLE;
2690 field->field_size = 0;
27304273 2691 *fixed_root = FIELD_VARIABLE;
2692 *fixed_parent = FIELD_VARIABLE;
3aee1200 2693 break;
2694 case LTT_STRING:
2695 field->fixed_size = FIELD_VARIABLE;
2696 field->field_size = 0;
27304273 2697 *fixed_root = FIELD_VARIABLE;
2698 *fixed_parent = FIELD_VARIABLE;
3aee1200 2699 break;
2700 case LTT_ARRAY:
2701 local_fixed_root = FIELD_VARIABLE;
2702 local_fixed_parent = FIELD_VARIABLE;
2703 preset_field_type_size(tf, event_type,
2704 0, 0,
2705 &local_fixed_root, &local_fixed_parent,
2706 field->child[0]);
2707 field->fixed_size = field->child[0]->fixed_size;
27304273 2708 if(field->fixed_size == FIELD_FIXED) {
3aee1200 2709 field->field_size = type->element_number * field->child[0]->field_size;
27304273 2710 } else {
3aee1200 2711 field->field_size = 0;
27304273 2712 *fixed_root = FIELD_VARIABLE;
2713 *fixed_parent = FIELD_VARIABLE;
2714 }
3aee1200 2715 break;
2716 case LTT_STRUCT:
2717 current_root_offset = field->offset_root;
2718 current_offset = 0;
2719 current_child_status = FIELD_FIXED;
2720 for(i=0;i<type->element_number;i++) {
2721 preset_field_type_size(tf, event_type,
2722 current_root_offset, current_offset,
2723 fixed_root, &current_child_status,
2724 field->child[i]);
2725 if(current_child_status == FIELD_FIXED) {
2726 current_root_offset += field->child[i]->field_size;
2727 current_offset += field->child[i]->field_size;
2728 } else {
2729 current_root_offset = 0;
2730 current_offset = 0;
2731 }
2732 }
2733 if(current_child_status != FIELD_FIXED) {
2734 *fixed_parent = current_child_status;
2735 field->field_size = 0;
2736 field->fixed_size = current_child_status;
2737 } else {
2738 field->field_size = current_offset;
2739 field->fixed_size = FIELD_FIXED;
2740 }
2741 break;
2742 case LTT_UNION:
2743 current_root_offset = field->offset_root;
2744 current_offset = 0;
2745 max_size = 0;
2746 final_child_status = FIELD_FIXED;
2747 for(i=0;i<type->element_number;i++) {
2748 enum field_status current_root_child_status = FIELD_FIXED;
2749 enum field_status current_child_status = FIELD_FIXED;
2750 preset_field_type_size(tf, event_type,
2751 current_root_offset, current_offset,
2752 &current_root_child_status, &current_child_status,
2753 field->child[i]);
2754 if(current_child_status != FIELD_FIXED)
2755 final_child_status = current_child_status;
2756 else
2757 max_size = max(max_size, field->child[i]->field_size);
2758 }
2759 if(final_child_status != FIELD_FIXED) {
62e4e7bf 2760 g_error("LTTV does not support variable size fields in unions.");
2761 /* This will stop the application. */
3aee1200 2762 *fixed_root = final_child_status;
2763 *fixed_parent = final_child_status;
2764 field->field_size = 0;
2765 field->fixed_size = current_child_status;
2766 } else {
2767 field->field_size = max_size;
2768 field->fixed_size = FIELD_FIXED;
2769 }
2770 break;
83e160f2 2771 case LTT_NONE:
2772 g_error("unexpected type NONE");
2773 break;
dfb73233 2774 }
2775
6cd62ccf 2776}
f104d082 2777#endif //0
3aee1200 2778
77175651 2779/*****************************************************************************
2780 *Function name
2781 * check_fields_compatibility : Check for compatibility between two fields :
2782 * do they use the same inner structure ?
2783 *Input params
2784 * event_type1 : event type
2785 * event_type2 : event type
2786 * field1 : field
2787 * field2 : field
2788 *Returns : 0 if identical
2789 * 1 if not.
2790 ****************************************************************************/
f104d082 2791// this function checks for equality of field types. Therefore, it does not use
2792// per se offsets. For instance, an aligned version of a structure is
2793// compatible with an unaligned version of the same structure.
3c165eaf 2794#if 0
f104d082 2795gint check_fields_compatibility(LttEventType *event_type1,
2796 LttEventType *event_type2,
2797 LttField *field1, LttField *field2)
2798{
2799 guint different = 0;
2312de30 2800 LttType *type1;
2801 LttType *type2;
f104d082 2802
2803 if(field1 == NULL) {
2804 if(field2 == NULL) goto end;
2805 else {
2806 different = 1;
2807 goto end;
2808 }
2809 } else if(field2 == NULL) {
2810 different = 1;
2811 goto end;
2812 }
2813
2312de30 2814 type1 = &field1->field_type;
2815 type2 = &field2->field_type;
f104d082 2816
2817 if(type1->type_class != type2->type_class) {
2818 different = 1;
2819 goto end;
2820 }
62e4e7bf 2821 if(type1->network != type2->network) {
2822 different = 1;
2823 goto end;
2824 }
f104d082 2825
2826 switch(type1->type_class) {
2827 case LTT_INT_FIXED:
2828 case LTT_UINT_FIXED:
2829 case LTT_POINTER:
2830 case LTT_CHAR:
2831 case LTT_UCHAR:
2832 case LTT_SHORT:
2833 case LTT_USHORT:
2834 case LTT_INT:
2835 case LTT_UINT:
2836 case LTT_LONG:
2837 case LTT_ULONG:
2838 case LTT_SIZE_T:
2839 case LTT_SSIZE_T:
2840 case LTT_OFF_T:
2841 case LTT_FLOAT:
2842 case LTT_ENUM:
2843 if(field1->field_size != field2->field_size)
2844 different = 1;
2845 break;
2846 case LTT_STRING:
2847 break;
2848 case LTT_ARRAY:
2849 {
2850 LttField *child1 = &g_array_index(type1->fields, LttField, 0);
2851 LttField *child2 = &g_array_index(type2->fields, LttField, 0);
2852
2853 if(type1->size != type2->size)
2854 different = 1;
2855 if(check_fields_compatibility(event_type1, event_type2, child1, child2))
2856 different = 1;
2857 }
2858 break;
2859 case LTT_SEQUENCE:
2860 {
2861 LttField *child1 = &g_array_index(type1->fields, LttField, 1);
2862 LttField *child2 = &g_array_index(type2->fields, LttField, 1);
2863
2864 if(check_fields_compatibility(event_type1, event_type2, child1, child2))
2865 different = 1;
2866 }
2867 break;
2868 case LTT_STRUCT:
2869 case LTT_UNION:
2870 {
2871 LttField *child;
2872 guint i;
2873
2874 if(type1->fields->len != type2->fields->len) {
2875 different = 1;
2876 goto end;
2877 }
2878
2879 for(i=0; i< type1->fields->len; i++) {
2312de30 2880 LttField *child1;
2881 LttField *child2;
f104d082 2882 child1 = &g_array_index(type1->fields, LttField, i);
2883 child2 = &g_array_index(type2->fields, LttField, i);
2884 different = check_fields_compatibility(event_type1,
2885 event_type2, child1, child2);
2886
2887 if(different) break;
2888 }
2889 }
2890 break;
2891 case LTT_NONE:
2892 default:
dd3a6d39 2893 g_error("check_fields_compatibility : unknown type");
f104d082 2894 }
2895
2896end:
2897 return different;
2898}
3c165eaf 2899#endif //0
f104d082 2900
2901#if 0
77175651 2902gint check_fields_compatibility(LttEventType *event_type1,
2903 LttEventType *event_type2,
2904 LttField *field1, LttField *field2)
2905{
2906 guint different = 0;
77175651 2907 guint i;
2908 LttType *type1;
2909 LttType *type2;
2910
2911 if(field1 == NULL) {
2912 if(field2 == NULL) goto end;
2913 else {
2914 different = 1;
2915 goto end;
2916 }
2917 } else if(field2 == NULL) {
2918 different = 1;
2919 goto end;
2920 }
2921
2922 g_assert(field1->fixed_root != FIELD_UNKNOWN);
2923 g_assert(field2->fixed_root != FIELD_UNKNOWN);
2924 g_assert(field1->fixed_parent != FIELD_UNKNOWN);
2925 g_assert(field2->fixed_parent != FIELD_UNKNOWN);
2926 g_assert(field1->fixed_size != FIELD_UNKNOWN);
2927 g_assert(field2->fixed_size != FIELD_UNKNOWN);
2928
2929 type1 = field1->field_type;
2930 type2 = field2->field_type;
2931
77175651 2932 if(type1->type_class != type2->type_class) {
2933 different = 1;
2934 goto end;
2935 }
2936 if(type1->element_name != type2->element_name) {
2937 different = 1;
2938 goto end;
2939 }
2940
2941 switch(type1->type_class) {
83e160f2 2942 case LTT_INT_FIXED:
2943 case LTT_UINT_FIXED:
2944 case LTT_POINTER:
2945 case LTT_CHAR:
2946 case LTT_UCHAR:
2947 case LTT_SHORT:
2948 case LTT_USHORT:
77175651 2949 case LTT_INT:
2950 case LTT_UINT:
2951 case LTT_FLOAT:
2952 case LTT_POINTER:
2953 case LTT_LONG:
2954 case LTT_ULONG:
2955 case LTT_SIZE_T:
2956 case LTT_SSIZE_T:
2957 case LTT_OFF_T:
2958 if(field1->field_size != field2->field_size) {
2959 different = 1;
2960 goto end;
2961 }
2962 break;
2963 case LTT_ENUM:
2964 if(type1->element_number != type2->element_number) {
2965 different = 1;
2966 goto end;
2967 }
2968 for(i=0;i<type1->element_number;i++) {
2969 if(type1->enum_strings[i] != type2->enum_strings[i]) {
2970 different = 1;
2971 goto end;
2972 }
2973 }
2974 break;
2975 case LTT_SEQUENCE:
2976 /* Two elements : size and child */
2977 g_assert(type1->element_number != type2->element_number);
2978 for(i=0;i<type1->element_number;i++) {
2979 if(check_fields_compatibility(event_type1, event_type2,
2980 field1->child[0], field2->child[0])) {
2981 different = 1;
2982 goto end;
2983 }
2984 }
2985 break;
2986 case LTT_STRING:
2987 break;
2988 case LTT_ARRAY:
2989 if(field1->field_size != field2->field_size) {
2990 different = 1;
2991 goto end;
2992 }
2993 /* Two elements : size and child */
2994 g_assert(type1->element_number != type2->element_number);
2995 for(i=0;i<type1->element_number;i++) {
2996 if(check_fields_compatibility(event_type1, event_type2,
2997 field1->child[0], field2->child[0])) {
2998 different = 1;
2999 goto end;
3000 }
3001 }
3002 break;
3003 case LTT_STRUCT:
3004 case LTT_UNION:
3005 if(type1->element_number != type2->element_number) {
3006 different = 1;
3007 break;
3008 }
3009 for(i=0;i<type1->element_number;i++) {
3010 if(check_fields_compatibility(event_type1, event_type2,
3011 field1->child[0], field2->child[0])) {
3012 different = 1;
3013 goto end;
3014 }
3015 }
3016 break;
3017 }
3018end:
3019 return different;
3020}
3aee1200 3021#endif //0
6cd62ccf 3022
f104d082 3023
6cd62ccf 3024/*****************************************************************************
3025 *Function name
eed2ef37 3026 * ltt_get_int : get an integer number
6cd62ccf 3027 *Input params
3aee1200 3028 * reverse_byte_order: must we reverse the byte order ?
6cd62ccf 3029 * size : the size of the integer
3aee1200 3030 * ptr : the data pointer
6cd62ccf 3031 *Return value
cf74a6f1 3032 * gint64 : a 64 bits integer
6cd62ccf 3033 ****************************************************************************/
3034
eed2ef37 3035gint64 ltt_get_int(gboolean reverse_byte_order, gint size, void *data)
6cd62ccf 3036{
3aee1200 3037 gint64 val;
cf74a6f1 3038
3039 switch(size) {
3aee1200 3040 case 1: val = *((gint8*)data); break;
3041 case 2: val = ltt_get_int16(reverse_byte_order, data); break;
3042 case 4: val = ltt_get_int32(reverse_byte_order, data); break;
3043 case 8: val = ltt_get_int64(reverse_byte_order, data); break;
3044 default: val = ltt_get_int64(reverse_byte_order, data);
3045 g_critical("get_int : integer size %d unknown", size);
cf74a6f1 3046 break;
3047 }
3048
3aee1200 3049 return val;
6cd62ccf 3050}
3aee1200 3051
6cd62ccf 3052/*****************************************************************************
3053 *Function name
eed2ef37 3054 * ltt_get_uint : get an unsigned integer number
6cd62ccf 3055 *Input params
3aee1200 3056 * reverse_byte_order: must we reverse the byte order ?
3057 * size : the size of the integer
3058 * ptr : the data pointer
3059 *Return value
3060 * guint64 : a 64 bits unsigned integer
6cd62ccf 3061 ****************************************************************************/
3062
eed2ef37 3063guint64 ltt_get_uint(gboolean reverse_byte_order, gint size, void *data)
6cd62ccf 3064{
3aee1200 3065 guint64 val;
3066
3067 switch(size) {
3068 case 1: val = *((gint8*)data); break;
3069 case 2: val = ltt_get_uint16(reverse_byte_order, data); break;
3070 case 4: val = ltt_get_uint32(reverse_byte_order, data); break;
3071 case 8: val = ltt_get_uint64(reverse_byte_order, data); break;
3072 default: val = ltt_get_uint64(reverse_byte_order, data);
3073 g_critical("get_uint : unsigned integer size %d unknown",
3074 size);
3075 break;
3076 }
3077
3078 return val;
6cd62ccf 3079}
3aee1200 3080
3081
a5dcde2f 3082/* get the node name of the system */
3083
3084char * ltt_trace_system_description_node_name (LttSystemDescription * s)
3085{
3086 return s->node_name;
3087}
3088
3089
3090/* get the domain name of the system */
3091
3092char * ltt_trace_system_description_domain_name (LttSystemDescription * s)
3093{
3094 return s->domain_name;
3095}
3096
3097
3098/* get the description of the system */
3099
3100char * ltt_trace_system_description_description (LttSystemDescription * s)
3101{
3102 return s->description;
3103}
3104
3105
bf33dd50 3106/* get the NTP corrected start time of the trace */
7bd563ec 3107LttTime ltt_trace_start_time(LttTrace *t)
a5dcde2f 3108{
7bd563ec 3109 return t->start_time;
a5dcde2f 3110}
3111
bf33dd50 3112/* get the monotonic start time of the trace */
3113LttTime ltt_trace_start_time_monotonic(LttTrace *t)
3114{
3115 return t->start_time_from_tsc;
3116}
3117
18206708 3118LttTracefile *ltt_tracefile_new()
3119{
3120 return g_new(LttTracefile, 1);
3121}
3122
3123void ltt_tracefile_destroy(LttTracefile *tf)
3124{
3125 g_free(tf);
3126}
3127
3128void ltt_tracefile_copy(LttTracefile *dest, const LttTracefile *src)
3129{
3130 *dest = *src;
3131}
3132
3aee1200 3133/* Before library loading... */
3134
3c165eaf 3135void init(void)
3aee1200 3136{
3137 LTT_FACILITY_NAME_HEARTBEAT = g_quark_from_string("heartbeat");
3138 LTT_EVENT_NAME_HEARTBEAT = g_quark_from_string("heartbeat");
d1bb700c 3139 LTT_EVENT_NAME_HEARTBEAT_FULL = g_quark_from_string("heartbeat_full");
3aee1200 3140
3865ea09 3141 LTT_TRACEFILE_NAME_FACILITIES = g_quark_from_string("/control/facilities");
3aee1200 3142}
This page took 0.219687 seconds and 4 git commands to generate.