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