genevent for 0.1.99.1
[lttv.git] / ltt / branches / poly / ltt-newlib / tracefile.c
CommitLineData
54ecbf38 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2005 Mathieu Desnoyers
3 *
4 * Complete rewrite from the original version made by XangXiu Yang.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License Version 2 as
8 * published by the Free Software Foundation;
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 * MA 02111-1307, USA.
19 */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
25#include <stdio.h>
26#include <fcntl.h>
27#include <string.h>
28#include <dirent.h>
29#include <sys/stat.h>
30#include <sys/types.h>
31#include <errno.h>
32#include <unistd.h>
33#include <math.h>
34#include <glib.h>
35#include <malloc.h>
36#include <sys/mman.h>
37
38// For realpath
39#include <limits.h>
40#include <stdlib.h>
41
42
43#include "parser.h"
44#include <ltt/ltt.h>
45#include "ltt-private.h"
46#include <ltt/trace.h>
47#include <ltt/facility.h>
48#include <ltt/event.h>
49#include <ltt/type.h>
50#include <ltt/ltt-types.h>
51
52
53/* Facility names used in this file */
54
55GQuark LTT_FACILITY_NAME_HEARTBEAT,
56 LTT_EVENT_NAME_HEARTBEAT;
57
58#ifndef g_open
59#define g_open open
60#endif
61
62
63#define __UNUSED__ __attribute__((__unused__))
64
65#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
66#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
67
68#define g_close close
69
70/* obtain the time of an event */
71
72static inline LttTime getEventTime(LttTracefile * tf);
73
74
75/* set the offset of the fields belonging to the event,
76 need the information of the archecture */
b59cd2f8 77void set_fields_offsets(LttTracefile *tf, LttEventType *event_type);
78size_t get_fields_offsets(LttTracefile *tf, LttEventType *event_type, void *data);
79
80/* get the size of the field type according to
81 * The facility size information. */
82static inline void preset_field_type_size(LttTracefile *tf,
83 LttEventType *event_type,
84 off_t offset_root, off_t offset_parent,
85 enum field_status *fixed_root, enum field_status *fixed_parent,
86 LttField *field)
87
88
89static inline size_t get_field_type_size(LttTracefile *tf,
90 LttEventType *event_type,
91 off_t offset_root, off_t offset_parent,
92 LttField *field, void *data)
54ecbf38 93
54ecbf38 94
2896f39c 95/* map a fixed size or a block information from the file (fd) */
54ecbf38 96int map_block(LttTracefile * tf, unsigned int block_num);
97
b59cd2f8 98/* calculate nsec per cycles for current block */
99static double calc_nsecs_per_cycle(LttTracefile * t);
54ecbf38 100
54ecbf38 101/* go to the next event */
2896f39c 102static int ltt_seek_next_event(LttTracefile *tf);
54ecbf38 103
104/* Functions to parse system.xml file (using glib xml parser) */
105static void parser_start_element (GMarkupParseContext __UNUSED__ *context,
106 const gchar *element_name,
107 const gchar **attribute_names,
108 const gchar **attribute_values,
109 gpointer user_data,
110 GError **error)
111{
112 int i=0;
113 LttSystemDescription* des = (LttSystemDescription* )user_data;
114 if(strcmp("system", element_name)){
115 *error = g_error_new(G_MARKUP_ERROR,
116 G_LOG_LEVEL_WARNING,
117 "This is not system.xml file");
118 return;
119 }
120
121 while(attribute_names[i]){
122 if(strcmp("node_name", attribute_names[i])==0){
123 des->node_name = g_strdup(attribute_values[i]);
124 }else if(strcmp("domainname", attribute_names[i])==0){
125 des->domain_name = g_strdup(attribute_values[i]);
126 }else if(strcmp("cpu", attribute_names[i])==0){
127 des->nb_cpu = atoi(attribute_values[i]);
128 }else if(strcmp("arch_size", attribute_names[i])==0){
129 if(strcmp(attribute_values[i],"LP32") == 0) des->size = LTT_LP32;
130 else if(strcmp(attribute_values[i],"ILP32") == 0) des->size = LTT_ILP32;
131 else if(strcmp(attribute_values[i],"LP64") == 0) des->size = LTT_LP64;
132 else if(strcmp(attribute_values[i],"ILP64") == 0) des->size = LTT_ILP64;
133 else if(strcmp(attribute_values[i],"UNKNOWN") == 0) des->size = LTT_UNKNOWN;
134 }else if(strcmp("endian", attribute_names[i])==0){
135 if(strcmp(attribute_values[i],"LITTLE_ENDIAN") == 0)
136 des->endian = LTT_LITTLE_ENDIAN;
137 else if(strcmp(attribute_values[i],"BIG_ENDIAN") == 0)
138 des->endian = LTT_BIG_ENDIAN;
139 }else if(strcmp("kernel_name", attribute_names[i])==0){
140 des->kernel_name = g_strdup(attribute_values[i]);
141 }else if(strcmp("kernel_release", attribute_names[i])==0){
142 des->kernel_release = g_strdup(attribute_values[i]);
143 }else if(strcmp("kernel_version", attribute_names[i])==0){
144 des->kernel_version = g_strdup(attribute_values[i]);
145 }else if(strcmp("machine", attribute_names[i])==0){
146 des->machine = g_strdup(attribute_values[i]);
147 }else if(strcmp("processor", attribute_names[i])==0){
148 des->processor = g_strdup(attribute_values[i]);
149 }else if(strcmp("hardware_platform", attribute_names[i])==0){
150 des->hardware_platform = g_strdup(attribute_values[i]);
151 }else if(strcmp("operating_system", attribute_names[i])==0){
152 des->operating_system = g_strdup(attribute_values[i]);
153 }else if(strcmp("ltt_major_version", attribute_names[i])==0){
154 des->ltt_major_version = atoi(attribute_values[i]);
155 }else if(strcmp("ltt_minor_version", attribute_names[i])==0){
156 des->ltt_minor_version = atoi(attribute_values[i]);
157 }else if(strcmp("ltt_block_size", attribute_names[i])==0){
158 des->ltt_block_size = atoi(attribute_values[i]);
159 }else{
160 *error = g_error_new(G_MARKUP_ERROR,
161 G_LOG_LEVEL_WARNING,
162 "Not a valid attribute");
163 return;
164 }
165 i++;
166 }
167}
168
169static void parser_characters (GMarkupParseContext __UNUSED__ *context,
170 const gchar *text,
171 gsize __UNUSED__ text_len,
172 gpointer user_data,
173 GError __UNUSED__ **error)
174{
175 LttSystemDescription* des = (LttSystemDescription* )user_data;
176 des->description = g_strdup(text);
177}
178
b59cd2f8 179static inline LttFacility *ltt_trace_get_facility_by_num(LttTrace *t,
180 guint num)
181{
182 g_assert(num < t->facilities_by_num->len);
183
184 return &g_array_index(t->facilities_by_num, LttFacility, num);
185
186}
187
54ecbf38 188
189/*****************************************************************************
190 *Function name
191 * ltt_tracefile_open : open a trace file, construct a LttTracefile
192 *Input params
193 * t : the trace containing the tracefile
194 * fileName : path name of the trace file
195 * tf : the tracefile structure
196 *Return value
197 * : 0 for success, -1 otherwise.
198 ****************************************************************************/
199
200int ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf)
201{
202 struct stat lTDFStat; /* Trace data file status */
203 struct ltt_block_start_header *header;
204
205 //open the file
206 tf->name = g_quark_from_string(fileName);
207 tf->trace = t;
208 tf->fd = g_open(fileName, O_RDONLY, 0);
209 if(tf->fd < 0){
210 g_warning("Unable to open input data file %s\n", fileName);
211 goto end;
212 }
213
214 // Get the file's status
215 if(fstat(tf->fd, &lTDFStat) < 0){
216 g_warning("Unable to get the status of the input data file %s\n", fileName);
217 goto close_file;
218 }
219
220 // Is the file large enough to contain a trace
221 if(lTDFStat.st_size < (off_t)(sizeof(BlockStart))){
222 g_print("The input data file %s does not contain a trace\n", fileName);
223 goto close_file;
224 }
225
226 /* Temporarily map the buffer start header to get trace information */
227 /* Multiple of pages aligned head */
228 tf->buffer.head = mmap(0, sizeof(struct ltt_block_start_header), PROT_READ,
229 tf->fd, 0);
230 if(tf->buffer == NULL) {
231 perror("Error in allocating memory for buffer of tracefile %s\n", fileName);
232 goto close_file;
233 }
234 g_assert(tf->buffer.head & (8-1) == 0); // make sure it's aligned.
235
236 header = (struct ltt_block_start_header*)tf->buffer.head;
237
238 if(header->traceset.magic_number == LTT_MAGIC_NUMBER)
239 tf->reverse_bo = 0;
240 else if(header->traceset.magic_number == LTT_REV_MAGIC_NUMBER)
241 tf->reverse_bo = 1;
242 else /* invalid magic number, bad tracefile ! */
243 goto unmap_file;
244
245 //store the size of the file
246 tf->file_size = lTDFStat.st_size;
247 tf->block_size = header->buf_size;
248 tf->block_number = tf->file_size / tf->block_size;
249
250 vfree(tf->buffer.head);
251 tf->buffer.head = NULL;
252
253 //read the first block
254 if(map_block(tf,0)) {
255 perror("Cannot map block %u for tracefile %s\n", 0, fileName);
256 goto close_file;
257 }
258
259 return 0;
260
261 /* Error */
262unmap_file:
263 munmap(tf->buffer.head, sizeof(struct ltt_block_start_header));
264close_file:
265 g_close(tf->fd);
266end:
267 return -1;
268}
269
270
271/*****************************************************************************
272 *Open control and per cpu tracefiles
273 ****************************************************************************/
274
275void ltt_tracefile_open_cpu(LttTrace *t, gchar * tracefile_name)
276{
277 LttTracefile * tf;
278 tf = ltt_tracefile_open(t,tracefile_name);
279 if(!tf) return;
280 t->per_cpu_tracefile_number++;
281 g_ptr_array_add(t->per_cpu_tracefiles, tf);
282}
283
284gint ltt_tracefile_open_control(LttTrace *t, gchar * control_name)
285{
286 LttTracefile * tf;
287 LttEvent ev;
288 LttFacility * f;
289 void * pos;
290 FacilityLoad fLoad;
291 unsigned int i;
292
293 tf = ltt_tracefile_open(t,control_name);
294 if(!tf) {
295 g_warning("ltt_tracefile_open_control : bad file descriptor");
296 return -1;
297 }
298 t->control_tracefile_number++;
299 g_ptr_array_add(t->control_tracefiles,tf);
300
301 //parse facilities tracefile to get base_id
302 if(strcmp(&control_name[strlen(control_name)-10],"facilities") ==0){
303 while(1){
304 if(!ltt_tracefile_read(tf,&ev)) return 0; // end of file
305
306 if(ev.event_id == TRACE_FACILITY_LOAD){
307 pos = ev.data;
308 fLoad.name = (gchar*)pos;
309 fLoad.checksum = *(LttChecksum*)(pos + strlen(fLoad.name));
310 fLoad.base_code = *(guint32 *)(pos + strlen(fLoad.name) + sizeof(LttChecksum));
311
312 for(i=0;i<t->facility_number;i++){
313 f = (LttFacility*)g_ptr_array_index(t->facilities,i);
314 if(strcmp(f->name,fLoad.name)==0 && fLoad.checksum==f->checksum){
315 f->base_id = fLoad.base_code;
316 break;
317 }
318 }
319 if(i==t->facility_number) {
320 g_warning("Facility: %s, checksum: %u is not found",
321 fLoad.name,(unsigned int)fLoad.checksum);
322 return -1;
323 }
324 }else if(ev.event_id == TRACE_BLOCK_START){
325 continue;
326 }else if(ev.event_id == TRACE_BLOCK_END){
327 break;
328 }else {
329 g_warning("Not valid facilities trace file");
330 return -1;
331 }
332 }
333 }
334 return 0;
335}
336
337/*****************************************************************************
338 *Function name
339 * ltt_tracefile_close: close a trace file,
340 *Input params
341 * t : tracefile which will be closed
342 ****************************************************************************/
343
344void ltt_tracefile_close(LttTracefile *t)
345{
346 if(t->buffer.head != NULL)
347 munmap(t->buffer.head, t->buf_size);
348 g_close(t->fd);
349}
350
351
352/*****************************************************************************
353 *Get system information
354 ****************************************************************************/
355gint getSystemInfo(LttSystemDescription* des, gchar * pathname)
356{
357 int fd;
358 GIOChannel *iochan;
359 gchar *buf = NULL;
360 gsize length;
361
362 GMarkupParseContext * context;
363 GError * error = NULL;
364 GMarkupParser markup_parser =
365 {
366 parser_start_element,
367 NULL,
368 parser_characters,
369 NULL, /* passthrough */
370 NULL /* error */
371 };
372
373 fd = g_open(pathname, O_RDONLY, 0);
374 if(fd == -1){
375 g_warning("Can not open file : %s\n", pathname);
376 return -1;
377 }
378
379 iochan = g_io_channel_unix_new(fd);
380
381 context = g_markup_parse_context_new(&markup_parser, 0, des,NULL);
382
383 //while(fgets(buf,DIR_NAME_SIZE, fp) != NULL){
384 while(g_io_channel_read_line(iochan, &buf, &length, NULL, &error)
385 != G_IO_STATUS_EOF) {
386
387 if(error != NULL) {
388 g_warning("Can not read xml file: \n%s\n", error->message);
389 g_error_free(error);
390 }
391 if(!g_markup_parse_context_parse(context, buf, length, &error)){
392 if(error != NULL) {
393 g_warning("Can not parse xml file: \n%s\n", error->message);
394 g_error_free(error);
395 }
396 g_markup_parse_context_free(context);
397
398 g_io_channel_shutdown(iochan, FALSE, &error); /* No flush */
399 if(error != NULL) {
400 g_warning("Can not close file: \n%s\n", error->message);
401 g_error_free(error);
402 }
403
404 close(fd);
405 return -1;
406 }
407 }
408 g_markup_parse_context_free(context);
409
410 g_io_channel_shutdown(iochan, FALSE, &error); /* No flush */
411 if(error != NULL) {
412 g_warning("Can not close file: \n%s\n", error->message);
413 g_error_free(error);
414 }
415
416 g_close(fd);
417
418 g_free(buf);
419 return 0;
420}
421
422/*****************************************************************************
423 *The following functions get facility/tracefile information
424 ****************************************************************************/
425
426gint getFacilityInfo(LttTrace *t, gchar* eventdefs)
427{
428 GDir * dir;
429 const gchar * name;
430 unsigned int i,j;
431 LttFacility * f;
432 LttEventType * et;
433 gchar fullname[DIR_NAME_SIZE];
434 GError * error = NULL;
435
436 dir = g_dir_open(eventdefs, 0, &error);
437
438 if(error != NULL) {
439 g_warning("Can not open directory: %s, %s\n", eventdefs, error->message);
440 g_error_free(error);
441 return -1;
442 }
443
444 while((name = g_dir_read_name(dir)) != NULL){
445 if(!g_pattern_match_simple("*.xml", name)) continue;
446 strcpy(fullname,eventdefs);
447 strcat(fullname,name);
448 ltt_facility_open(t,fullname);
449 }
450 g_dir_close(dir);
451
452 for(j=0;j<t->facility_number;j++){
453 f = (LttFacility*)g_ptr_array_index(t->facilities, j);
454 for(i=0; i<f->event_number; i++){
455 et = f->events[i];
456 setFieldsOffset(NULL, et, NULL, t);
457 }
458 }
459 return 0;
460}
461
462/*****************************************************************************
463 *A trace is specified as a pathname to the directory containing all the
464 *associated data (control tracefiles, per cpu tracefiles, event
465 *descriptions...).
466 *
467 *When a trace is closed, all the associated facilities, types and fields
468 *are released as well.
469 */
470
471
472/****************************************************************************
473 * get_absolute_pathname
474 *
475 * return the unique pathname in the system
476 *
477 * MD : Fixed this function so it uses realpath, dealing well with
478 * forgotten cases (.. were not used correctly before).
479 *
480 ****************************************************************************/
481void get_absolute_pathname(const gchar *pathname, gchar * abs_pathname)
482{
483 abs_pathname[0] = '\0';
484
485 if ( realpath (pathname, abs_pathname) != NULL)
486 return;
487 else
488 {
489 /* error, return the original path unmodified */
490 strcpy(abs_pathname, pathname);
491 return;
492 }
493 return;
494}
495
496/* Search for something like : .*_.*
497 *
498 * The left side is the name, the right side is the number.
499 */
500
501int get_tracefile_name_number(const gchar *raw_name,
502 GQuark *name,
503 guint *num)
504{
505 guint raw_name_len = strlen(raw_name);
506 gchar char_name[PATH_MAX]
507 gchar *digit_begin;
508 int i;
509 int underscore_pos;
510 long int cpu_num;
511 gchar *endptr;
512
513 for(i=raw_name_len-1;i>=0;i--) {
514 if(raw_name[i] == '_') break;
515 }
516 if(i==0) /* Either not found or name length is 0 */
517 return -1;
518 underscore_pos = i;
519
520 cpu_num = strtol(raw_name+underscore_pos+1, &endptr, 10);
521
522 if(endptr == raw_name+underscore_pos+1)
523 return -1; /* No digit */
524 if(cpu_num == LONG_MIN || cpu_num == LONG_MAX)
525 return -1; /* underflow / overflow */
526
527 char_name = strncpy(char_name, raw_name, underscore_pos);
528
529 *name = g_quark_from_string(char_name);
530 *num = cpu_num;
531
532 return 0;
533}
534
535
536void ltt_tracefile_group_destroy(gpointer data)
537{
538 GArray *group = (GArray *)data;
539 int i;
540 LttTracefile *tf;
541
542 for(i=0; i<group->len; i++) {
543 tf = &g_array_index (group, LttTracefile, i);
544 if(tf->cpu_online)
545 ltt_tracefile_close(tf);
546 }
2896f39c 547 g_array_free(group, TRUE);
54ecbf38 548}
549
550gboolean ltt_tracefile_group_has_cpu_online(gpointer data)
551{
552 GArray *group = (GArray *)data;
553 int i;
554 LttTracefile *tf;
555
556 for(i=0; i<group->len; i++) {
557 tf = &g_array_index (group, LttTracefile, i);
558 if(tf->cpu_online) return 1;
559 }
560 return 0;
561}
562
563
564/* Open each tracefile under a specific directory. Put them in a
565 * GData : permits to access them using their tracefile group pathname.
566 * i.e. access control/modules tracefile group by index :
567 * "control/module".
568 *
569 * A tracefile group is simply an array where all the per cpu tracefiles sits.
570 */
571
572static int open_tracefiles(LttTrace *trace, char *root_path, GData *tracefiles)
573{
574 DIR *dir = opendir(root_path);
575 struct dirent *entry;
576 struct stat stat_buf;
577 int ret;
578 char path[PATH_MAX];
579 int path_len;
580 char *path_ptr;
581
582 if(channel_dir == NULL) {
583 perror(subchannel_name);
584 return ENOENT;
585 }
586
587 strncpy(path, root_path, PATH_MAX-1);
588 path_len = strlen(path);
589 path[path_len] = '/';
590 path_len++;
591 path_ptr = path + path_len;
592
593 while((entry = readdir(channel_dir)) != NULL) {
594
595 if(entry->d_name[0] == '.') continue;
596
597 strncpy(path_ptr, entry->d_name, PATH_MAX - path_len);
598
599 ret = stat(path, &stat_buf);
600 if(ret == -1) {
601 perror(path);
602 continue;
603 }
604
605 g_debug("Tracefile file or directory : %s\n", path);
606
607 if(S_ISDIR(stat_buf.st_mode)) {
608
609 g_debug("Entering subdirectory...\n");
610 ret = open_tracefiles(path, tracefiles);
611 if(ret < 0) continue;
612 } else if(S_ISREG(stat_buf.st_mode)) {
613 g_debug("Opening file.\n");
614
615 GQuark name;
616 guint num;
617 GArray *group;
618 LttTracefile *tf;
619 guint len;
620
621 if(get_tracefile_name_number(path, &name, &num))
622 continue; /* invalid name */
623
624 group = g_datalist_get_data(tracefiles, name);
625 if(group == NULL) {
626 /* Elements are automatically cleared when the array is allocated.
627 * It makes the cpu_online variable set to 0 : cpu offline, by default.
628 */
629 group = g_array_sized_new (FALSE, TRUE, sizeof(LttTracefile), 10);
630 g_datalist_set_data_full(tracefiles, name,
631 group, ltt_tracefile_group_destroy);
632 }
633 /* Add the per cpu tracefile to the named group */
634 unsigned int old_len = group->len;
635 if(num+1 > old_len)
2896f39c 636 group = g_array_set_size(group, num+1);
54ecbf38 637 tf = &g_array_index (group, LttTracefile, num);
638
639 if(ltt_tracefile_open(trace, path, tf)) {
640 g_info("Error opening tracefile %s", path);
641 g_array_set_size(group, old_len);
642
643 if(!ltt_tracefile_group_has_cpu_online(group))
644 g_datalist_remove_data(tracefiles, name);
645
646 continue; /* error opening the tracefile : bad magic number ? */
647 }
648 tf->cpu_online = 1;
b59cd2f8 649 tf->cpu_num = num;
54ecbf38 650 }
651 }
652
653 closedir(dir);
654
655 return 0;
656}
657
2896f39c 658/* ltt_get_facility_description
659 *
660 * Opens the trace corresponding to the requested facility (identified by fac_id
661 * and checksum).
662 *
663 * The name searched is : %trace root%/eventdefs/facname_checksum.xml
664 *
665 * Returns 0 on success, or 1 on failure.
666 */
667
668static int ltt_get_facility_description(LttFacility *f,
669 LttTrace *t)
670{
671 char desc_file_name[PATH_MAX];
672 char *text;
673 guint textlen;
674 gint err;
b59cd2f8 675 int i, j;
2896f39c 676
677 text = g_quark_to_string(t->pathname);
678 textlen = strlen(text);
679
680 if(textlen >= PATH_MAX) goto name_error;
681 strcpy(desc_file_name, text);
682
683 text = "/eventdefs/";
684 textlen+=strlen(text);
685 if(textlen >= PATH_MAX) goto name_error;
686 strcat(desc_file_name, text);
687
688 text = g_quark_to_string(f->name);
689 textlen+=strlen(text);
690 if(textlen >= PATH_MAX) goto name_error;
691 strcat(desc_file_name, text);
692
693 text = "_";
694 textlen+=strlen(text);
695 if(textlen >= PATH_MAX) goto name_error;
696 strcat(desc_file_name, text);
697
698 err = snprintf(desc_file_name+textlen, PATH_MAX-textlen-1,
699 "%u", f->checksum);
700 if(err) goto name_error;
701
702 textlen=strlen(desc_file_name);
703
704 text = ".xml";
705 textlen+=strlen(text);
706 if(textlen >= PATH_MAX) goto name_error;
707 strcat(desc_file_name, text);
708
709 err = ltt_facility_open(f, t, desc_file_name);
710 if(err) goto facility_error;
711
b59cd2f8 712 for(i=0;i<t->facilities_by_num->len;i++){
713 f = &g_array_index(t->facilities_by_num, LttFacility, i);
714 if(f->exists) {
715 for(j=0; j<f->events->len; j++){
716 et = &g_array_index(f->events, LttEventType, j);
717 setFieldsOffset(NULL, et, NULL);
718 }
719 }
720 }
721
722
2896f39c 723 return 0;
724
725facility_error:
726name_error:
727 return 1;
728}
729
730static void ltt_tracefile_ids_destroy(gpointer data)
731{
732 GArray *fac_ids = (GArray *)data;
733 int i;
734 LttFacility *fac;
735
736 for(i=0; i<group->len; i++) {
737 fac = &g_array_index (fac_ids, LttFacility, i);
738 ltt_facility_close(fac);
739 }
740
741 g_array_free(array, TRUE);
742}
743
744
745/* Presumes the tracefile is already seeked at the beginning. It makes sense,
746 * because it must be done just after the opening */
747static int ltt_process_facility_tracefile(LttTracefile *tf)
748{
749 int err;
750 LttFacility *fac;
751 GArray *fac_ids;
752
753 while(1) {
754 err = ltt_tracefile_read_seek(tf);
755 if(err == EPERM) goto seek_error;;
756 else if(err == ERANGE) break; /* End of tracefile */
757
758 err = ltt_tracefile_read_update_event(tf);
759 if(err) goto update_error;
760
761 /* We are on a facility load/or facility unload/ or heartbeat event */
762 /* The rules are :
763 * * facility 0 is hardcoded : this is the core facility. It will be shown
764 * in the facility array though, and is shown as "loaded builtin" in the
765 * trace.
766 * It contains event :
767 * 0 : facility load
768 * 1 : facility unload
769 * 2 : state dump facility load
770 * Facility 1 : (heartbeat)
771 * 0 : heartbeat
772 */
773 if(tf->event.facility_id > 1) { /* Should only contain core and heartbeat
774 facilities */
775 g_warning("Error in processing facility file %s, "
776 "should not contain facility id %u.", g_quark_to_string(tf->name),
777 tf->event.facility_id);
778 err = EPERM;
779 goto fac_id_error;
780 } else if(tf->event.facility_id == 0) {
781
782 // FIXME align
783 switch((enum ltt_core_events)tf->event.event_id) {
784 case LTT_EVENT_FACILITY_LOAD:
785 struct LttFacilityLoad *fac_load_data =
786 (struct LttFacilityLoad *)tf->event.data;
787 char *fac_name =
788 (char*)(tf->event.data + sizeof(struct LttFacilityLoad));
789 fac = &g_array_index (tf->facilities_by_num, LttTracefile,
790 tf->event.);
791 g_assert(fac->exists == 0);
792 fac->name = g_quark_from_string(fac_name);
793 fac->checksum = ltt_get_uint32(LTT_GET_BO(tf),
794 fac_load_data->checksum);
795 fac->id = ltt_get_uint8(LTT_GET_BO(tf), fac_load_data->id);
796 fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf),
797 fac_load_data->pointer_size);
798 fac->size_t_size = ltt_get_uin32(LTT_GET_BO(tf),
799 fac_load_data->size_t_size);
800 fac->alignment = ltt_get_uint32(LTT_GET_BO(tf),
801 fac_load_data->alignment);
802
803 if(ltt_get_facility_description(fac, tf->trace))
804 goto facility_error;
b59cd2f8 805
806 fac->trace = tf->trace;
2896f39c 807 fac->exists = 1;
808
809 fac_ids = g_datalist_get_data(tf->facilities_by_name, fac->name);
810 if(fac_ids == NULL) {
811 fac_ids = g_array_sized_new (FALSE, TRUE, sizeof(guint), 1);
812 g_datalist_set_data_full(tf->facilities_by_name, fac->name,
813 fac_ids, ltt_fac_ids_destroy);
814 }
815 g_array_append_val(fac_ids, fac->id);
816
817 break;
818 case LTT_EVENT_FACILITY_UNLOAD:
819 /* We don't care about unload : facilities ID are valid for the whole
820 * trace. They simply won't be used after the unload. */
821 break;
822 case LTT_EVENT_STATE_DUMP_FACILITY_LOAD:
823 struct LttFacilityLoad *fac_load_data =
824 (struct LttFacilityLoad *)tf->event.data;
825 char *fac_name =
826 (char*)(tf->event.data + sizeof(struct LttFacilityLoad));
827 fac = &g_array_index (tf->facilities_by_num, LttTracefile,
828 tf->event.);
829 g_assert(fac->exists == 0);
830 fac->name = g_quark_from_string(fac_name);
831 fac->checksum = ltt_get_uint32(LTT_GET_BO(tf),
832 fac_load_data->checksum);
833 fac->id = ltt_get_uint8(LTT_GET_BO(tf), fac_load_data->id);
834 fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf),
835 fac_load_data->pointer_size);
836 fac->size_t_size = ltt_get_uin32(LTT_GET_BO(tf),
837 fac_load_data->size_t_size);
838 fac->alignment = ltt_get_uint32(LTT_GET_BO(tf),
839 fac_load_data->alignment);
840 fac->events;
841 fac->named_types;
842 fac->named_types_number;
843 fac->exists = 1;
844
845 fac_ids = g_datalist_get_data(tf->facilities_by_name, fac->name);
846 if(fac_ids == NULL) {
847 fac_ids = g_array_sized_new (FALSE, TRUE, sizeof(guint), 1);
848 g_datalist_set_data_full(tf->facilities_by_name, fac->name,
849 fac_ids, ltt_fac_ids_destroy);
850 }
851 g_array_append_val(fac_ids, fac->id);
852
853 break;
854 default:
855 g_warning("Error in processing facility file %s, "
856 "unknown event id %hhu in core facility.",
857 g_quark_to_string(tf->name),
858 tf->event.event_id);
859 err = EPERM;
860 goto event_id_error;
861 }
862 } else if(tf->event.facility_id == 1) {
863
864 switch((enum ltt_heartbeat_events)tf->event.event_id) {
865 case LTT_EVENT_HEARTBEAT:
866 break;
867 default:
868 g_warning("Error in processing facility file %s, "
869 "unknown event id %hhu in heartbeat facility.",
870 g_quark_to_string(tf->name),
871 tf->event.event_id);
872 err = EPERM;
873 goto event_id_error;
874 }
875 }
876 }
877 return 0;
878
879 /* Error handling */
880facility_error:
881event_id_error:
882fac_id_error:
883update_error:
884seek_error:
885 return err;
886}
887
888
54ecbf38 889LttTrace *ltt_trace_open(const gchar *pathname)
890{
891 gchar abs_path[PATH_MAX];
892 LttTrace * t;
2896f39c 893 LttTracefile *tf;
54ecbf38 894 GArray *group;
895 int i;
896
897 LttTrace * t = g_new(LttTrace, 1);
898 if(!t) goto alloc_error;
899
900 get_absolute_pathname(pathname, abs_path);
901 t->pathname = g_quark_from_string(abs_path);
902
903 /* Open all the tracefiles */
904 g_datalist_init(t->tracefiles);
905 if(open_tracefiles(t, abs_path, t->tracefiles))
906 goto open_error;
907
2896f39c 908 /* Prepare the facilities containers : array and mapping */
909 /* Array is zeroed : the "exists" field is set to false by default */
910 t->facilities_by_num = g_array_sized_new (FALSE,
911 TRUE, sizeof(LttFacility),
912 NUM_FACILITIES);
913 t->facilities_by_num = g_array_set_size(t->facilities_by_num, NUM_FACILITIES);
914
915 g_datalist_init(t->tracefiles_by_name);
916
54ecbf38 917 /* Parse each trace control/facilitiesN files : get runtime fac. info */
918 group = g_datalist_get_data(t->tracefiles, LTT_TRACEFILE_NAME_FACILITIES);
919 if(group == NULL) {
920 g_error("Trace %s has no facility tracefile", abs_path);
921 goto facilities_error;
922 }
923
924 for(i=0; i<group->len; i++) {
925 tf = &g_array_index (group, LttTracefile, i);
2896f39c 926 if(ltt_process_facility_tracefile(tf))
927 goto facilities_error;
54ecbf38 928 }
929
930
931
932 return t;
933
934 /* Error handling */
935facilities_error:
2896f39c 936 g_datalist_free(t->tracefiles_by_name);
937 g_array_free(t->facilities_by_num, TRUE);
54ecbf38 938open_error:
939 g_datalist_clear(t->tracefiles);
940 g_free(t);
941alloc_error:
942 return NULL;
943
54ecbf38 944}
945
2896f39c 946GQuark ltt_trace_name(LttTrace *t)
54ecbf38 947{
948 return t->pathname;
949}
950
951
952/******************************************************************************
953 * When we copy a trace, we want all the opening actions to happen again :
954 * the trace will be reopened and totally independant from the original.
955 * That's why we call ltt_trace_open.
956 *****************************************************************************/
957LttTrace *ltt_trace_copy(LttTrace *self)
958{
959 return ltt_trace_open(self->pathname);
960}
961
962void ltt_trace_close(LttTrace *t)
963{
b59cd2f8 964 g_datalist_free(t->tracefiles_by_name);
965 g_array_free(t->facilities_by_num, TRUE);
966 g_datalist_clear(t->tracefiles);
54ecbf38 967 g_free(t);
54ecbf38 968}
969
970
971/*****************************************************************************
972 *Get the system description of the trace
973 ****************************************************************************/
974
2896f39c 975LttFacility *ltt_trace_facility_by_id(LttTrace *t, guint8 id)
54ecbf38 976{
2896f39c 977 g_assert(index < t->facilities_by_num->len);
978 return &g_array_index(t->facilities_by_num, LttFacility, id);
54ecbf38 979}
980
2896f39c 981/* ltt_trace_facility_get_by_name
982 *
983 * Returns the GArray of facility indexes. All the fac_ids that matches the
984 * requested facility name.
985 *
986 * If name is not found, returns NULL.
987 */
988GArray *ltt_trace_facility_get_by_name(LttTrace *t, GQuark name)
54ecbf38 989{
2896f39c 990 return g_datalist_id_get_data(t->facilities_by_name, name);
54ecbf38 991}
992
993/*****************************************************************************
994 * Functions to discover all the event types in the trace
995 ****************************************************************************/
996
b59cd2f8 997#if 0
54ecbf38 998unsigned ltt_trace_eventtype_number(LttTrace *t)
999{
1000 unsigned int i;
1001 unsigned count = 0;
1002 unsigned int num = t->facility_number;
1003 LttFacility * f;
1004
1005 for(i=0;i<num;i++){
1006 f = (LttFacility*)g_ptr_array_index(t->facilities, i);
1007 count += f->event_number;
1008 }
1009 return count;
1010}
b59cd2f8 1011#endif //0
54ecbf38 1012
b59cd2f8 1013#if 0
1014//use an iteration on all the trace facilities, and inside iteration on all the
1015//event types in each facilities instead.
54ecbf38 1016LttEventType *ltt_trace_eventtype_get(LttTrace *t, unsigned evId)
1017{
1018 LttEventType *event_type;
1019
1020 LttFacility * f;
1021 f = ltt_trace_facility_by_id(t,evId);
1022
1023 if(unlikely(!f)) event_type = NULL;
1024 else event_type = f->events[evId - f->base_id];
1025
1026 return event_type;
1027}
b59cd2f8 1028#endif //0
54ecbf38 1029
2896f39c 1030#if 0
54ecbf38 1031/*****************************************************************************
2896f39c 1032 * ltt_trace_find_tracefile
1033 *
1034 * Find a tracefile by name and index in the group.
1035 *
1036 * Returns a pointer to the tracefiles, else NULL.
54ecbf38 1037 ****************************************************************************/
1038
2896f39c 1039LttTracefile *ltt_trace_find_tracefile(LttTrace *t, const gchar *name)
54ecbf38 1040{
54ecbf38 1041}
2896f39c 1042#endif //0
54ecbf38 1043
1044/*****************************************************************************
1045 * Get the start time and end time of the trace
1046 ****************************************************************************/
1047
1048static void ltt_tracefile_time_span_get(LttTracefile *tf,
1049 LttTime *start, LttTime *end)
1050{
1051 struct ltt_block_start_header * header;
1052 int err;
1053
1054 err = map_block(tf, 0);
1055 if(unlikely(err)) {
1056 g_error("Can not map block");
1057 *start = { 0xFFFFFFFF, 0xFFFFFFFF };
1058 } else
1059 *start = tf->buffer.begin.timestamp;
1060
1061 err = map_block(tf, tf->num_blocks - 1); /* Last block */
1062 if(unlikely(err)) {
1063 g_error("Can not map block");
1064 *end = { 0, 0 };
1065 } else
1066 *end = tf->buffer.end.timestamp;
1067}
1068
1069struct tracefile_time_span_get_args {
1070 LttTrace *t;
1071 LttTime *start;
1072 LttTime *end;
1073};
1074
1075static void group_time_span_get(GQuark name, gpointer data, gpointer user_data)
1076{
1077 struct tracefile_time_span_get_args *args =
1078 (struct tracefile_time_span_get_args*)user_data;
1079
1080 GArray *group = (GArray *)data;
1081 int i;
1082 LttTracefile *tf;
1083 LttTime tmp_start;
1084 LttTime tmp_end;
1085
1086 for(i=0; i<group->len; i++) {
1087 tf = &g_array_index (group, LttTracefile, i);
1088 if(tf->cpu_online) {
1089 ltt_tracefile_time_span_get(tf, &tmp_start, &tmp_end);
1090 if(ltt_time_compare(*args->start, tmp_start)>0) *args->start = tmp_start;
1091 if(ltt_time_compare(*args->end, tmp_end)<0) *args->end = tmp_end;
1092 }
1093 }
1094}
1095
1096void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end)
1097{
1098 LttTime min_start = { 0xFFFFFFFF, 0xFFFFFFFF };
1099 LttTime max_end = { 0, 0 };
1100 struct tracefile_time_span_get_args args = { t, &min_start, &max_end };
1101
1102 g_datalist_foreach(t->tracefiles, &group_time_span_get, &args);
1103
1104 if(start != NULL) *start = min_start;
1105 if(end != NULL) *end = max_end;
1106
1107}
1108
1109
1110/*****************************************************************************
1111 *Get the name of a tracefile
1112 ****************************************************************************/
1113
2896f39c 1114GQuark ltt_tracefile_name(LttTracefile *tf)
54ecbf38 1115{
1116 return tf->name;
1117}
1118
1119/*****************************************************************************
1120 * Get the number of blocks in the tracefile
1121 ****************************************************************************/
1122
2896f39c 1123guint ltt_tracefile_block_number(LttTracefile *tf)
54ecbf38 1124{
1125 return tf->block_number;
1126}
1127
1128
1129/* Seek to the first event in a tracefile that has a time equal or greater than
1130 * the time passed in parameter.
1131 *
1132 * If the time parameter is outside the tracefile time span, seek to the first
1133 * or the last event of the tracefile.
1134 *
1135 * If the time parameter is before the first event, we have to seek specially to
1136 * there.
1137 *
1138 * If the time is after the end of the trace, get the last event.
1139 *
1140 * Do a binary search to find the right block, then a sequential search in the
1141 * block to find the event.
1142 *
1143 * In the special case where the time requested fits inside a block that has no
1144 * event corresponding to the requested time, the first event of the next block
1145 * will be seeked.
1146 *
1147 * IMPORTANT NOTE : // FIXME everywhere...
1148 *
1149 * You MUST NOT do a ltt_tracefile_read right after a ltt_tracefile_seek_time :
1150 * you will jump over an event if you do.
1151 *
2896f39c 1152 * Return value : 0 : no error, the tf->event can be used
1153 * otherwise : this is an error.
1154 *
54ecbf38 1155 * */
1156
2896f39c 1157int ltt_tracefile_seek_time(LttTracefile *tf, LttTime time)
54ecbf38 1158{
2896f39c 1159 int ret = 0;
54ecbf38 1160 int err;
1161 unsigned int block_num, high, low;
1162
1163 /* seek at the beginning of trace */
1164 err = map_block(tf, 0); /* First block */
1165 if(unlikely(err)) {
1166 g_error("Can not map block");
1167 goto fail;
1168 }
1169
1170 /* If the time is lower or equal the beginning of the trace,
1171 * go to the first event. */
1172 if(ltt_time_compare(time, tf->buffer.start.timestamp) <= 0) {
2896f39c 1173 ret = ltt_tracefile_read(tf)
54ecbf38 1174 goto found; /* There is either no event in the trace or the event points
1175 to the first event in the trace */
1176 }
1177
1178 err = map_block(tf, tf->num_blocks - 1); /* Last block */
1179 if(unlikely(err)) {
1180 g_error("Can not map block");
1181 goto fail;
1182 }
1183
1184 /* If the time is after the end of the trace, get the last event. */
1185 if(ltt_time_compare(time, tf->buffer.end.timestamp) >= 0) {
2896f39c 1186 /* While the ltt_tracefile_read doesn't return ERANGE or EPERM,
1187 * continue reading.
54ecbf38 1188 */
2896f39c 1189 while(1) {
1190 ret = ltt_tracefile_read(tf);
1191 if(ret == ERANGE) goto found; /* ERANGE or EPERM */
1192 else if(ret) goto fail;
1193 }
54ecbf38 1194 }
1195
1196 /* Binary search the block */
1197 high = tf->num_blocks - 1;
1198 low = 0;
1199
1200 while(1) {
1201 block_num = ((high-low) / 2) + low;
1202
1203 err = map_block(tf, block_num);
1204 if(unlikely(err)) {
1205 g_error("Can not map block");
1206 goto fail;
1207 }
bed09760 1208 if(high == low) {
1209 /* We cannot divide anymore : this is what would happen if the time
1210 * requested was exactly between two consecutive buffers'end and start
1211 * timestamps. This is also what would happend if we didn't deal with out
1212 * of span cases prior in this function. */
1213 /* The event is right in the buffer!
1214 * (or in the next buffer first event) */
1215 while(1) {
2896f39c 1216 ret = ltt_tracefile_read(tf);
1217 if(ret == ERANGE) goto found; /* ERANGE or EPERM */
1218 else if(ret) goto fail;
1219
bed09760 1220 if(ltt_time_compare(time, tf->event.event_time) >= 0)
1221 break;
1222 }
1223
1224 } if(ltt_time_compare(time, tf->buffer.start.timestamp) < 0) {
54ecbf38 1225 /* go to lower part */
1226 high = block_num;
1227 } else if(ltt_time_compare(time, tf->buffer.end.timestamp) > 0) {
1228 /* go to higher part */
1229 low = block_num;
1230 } else {/* The event is right in the buffer!
1231 (or in the next buffer first event) */
1232 while(1) {
1233 ltt_tracefile_read(tf);
2896f39c 1234 if(ret == ERANGE) goto found; /* ERANGE or EPERM */
1235 else if(ret) goto fail;
1236
54ecbf38 1237 if(ltt_time_compare(time, tf->event.event_time) >= 0)
1238 break;
1239 }
1240 goto found;
1241 }
1242 }
1243
1244found:
2896f39c 1245 return 0;
54ecbf38 1246
1247 /* Error handling */
1248fail:
1249 g_error("ltt_tracefile_seek_time failed on tracefile %s",
1250 g_quark_to_string(tf->name));
2896f39c 1251 return EPERM;
54ecbf38 1252}
1253
1254
1255int ltt_tracefile_seek_position(LttTracefile *tf, const LttEventPosition *ep) {
1256
1257 int err;
1258
1259 if(ep->tracefile != tf) {
1260 goto fail;
1261 }
1262
1263 err = map_block(tf, ep->block);
1264 if(unlikely(err)) {
1265 g_error("Can not map block");
1266 goto fail;
1267 }
1268
1269 tf->event.offset = ep->offset;
1270
2896f39c 1271 err = ltt_tracefile_read_update_event(tf);
1272 if(err) goto fail;
1273 err = ltt_tracefile_read_op(tf);
1274 if(err) goto fail;
1275
54ecbf38 1276 return;
1277
1278fail:
1279 g_error("ltt_tracefile_seek_time failed on tracefile %s",
1280 g_quark_to_string(tf->name));
1281}
1282
54ecbf38 1283/* Calculate the real event time based on the buffer boundaries */
1284LttTime ltt_interpolate_time(LttTracefile *tf, LttEvent *event)
1285{
1286 LttTime time;
1287
1288 g_assert(t->trace->has_tsc);
1289
1290 time = ltt_time_from_uint64(
1291 (guint64)tf->buffer.tsc*tf->buffer.nsecs_per_cycle);
1292 time = ltt_time_add(tf->buffer.begin.timestamp, time);
1293
1294 return time;
1295}
1296
54ecbf38 1297/*****************************************************************************
1298 *Function name
1299 * ltt_tracefile_read : Read the next event in the tracefile
1300 *Input params
1301 * t : tracefile
1302 *Return value
54ecbf38 1303 *
2896f39c 1304 * Returns 0 if an event can be used in tf->event.
1305 * Returns ERANGE on end of trace. The event in tf->event still can be used.
1306 * Returns EPERM on error.
54ecbf38 1307 *
1308 * This function does make the tracefile event structure point to the event
2896f39c 1309 * currently pointed to by the tf->event.
1310 *
1311 * Note : you must call a ltt_tracefile_seek to the beginning of the trace to
1312 * reinitialize it after an error if you want results to be coherent.
1313 * It would be the case if a end of trace last buffer has no event : the end
1314 * of trace wouldn't be returned, but an error.
1315 * We make the assumption there is at least one event per buffer.
54ecbf38 1316 ****************************************************************************/
1317
2896f39c 1318int ltt_tracefile_read(LttTracefile *tf)
1319{
1320 int err;
1321
1322 err = ltt_tracefile_read_seek(tf);
1323 if(err) return err;
1324 err = ltt_tracefile_read_update_event(tf);
1325 if(err) return err;
1326 err = ltt_tracefile_read_op(tf);
1327 if(err) return err;
1328
1329 return 0;
1330}
1331
1332int ltt_tracefile_read_seek(LttTracefile *tf)
1333{
1334 int err;
1335
1336 /* Get next buffer until we finally have an event, or end of trace */
1337 while(1) {
1338 err = ltt_seek_next_event(tf);
1339 if(unlikely(err == ENOPROTOOPT)) {
1340 return EPERM;
1341 }
1342
1343 /* Are we at the end of the buffer ? */
1344 if(err == ERANGE) {
1345 if(unlikely(tf->buffer.index == tf->num_blocks-1)){ /* end of trace ? */
1346 return ERANGE;
1347 } else {
1348 /* get next block */
1349 err = map_block(tf, tf->buffer.index + 1);
1350 if(unlikely(err)) {
1351 g_error("Can not map block");
1352 return EPERM;
1353 }
1354 }
1355 } else break; /* We found an event ! */
1356 }
1357
1358 return 0;
1359}
1360
1361
1362/* do specific operation on events */
1363int ltt_tracefile_read_op(LttTracefile *tf)
54ecbf38 1364{
1365 int err;
1366 LttFacility *f;
1367 void * pos;
2896f39c 1368 LttEvent *event;
54ecbf38 1369
2896f39c 1370 event = &tf->event;
54ecbf38 1371
2896f39c 1372 /* do event specific operation */
1373
1374 /* do something if its an heartbeat event : increment the heartbeat count */
b59cd2f8 1375 if(event->facility_id == LTT_FACILITY_CORE)
1376 if(event->event_id == LTT_EVENT_HEARTBEAT)
1377 t->cur_heart_beat_number++;
2896f39c 1378
1379 return 0;
1380}
1381
1382
1383/* same as ltt_tracefile_read, but does not seek to the next event nor call
1384 * event specific operation. */
1385int ltt_tracefile_read_update_event(LttTracefile *tf)
1386{
1387 int err;
1388 LttFacility *f;
1389 void * pos;
1390 LttEvent *event;
1391
1392 event = &tf->event;
1393 pos = event->offset;
54ecbf38 1394
1395 /* Read event header */
1396
1397 //TODO align
1398
1399 if(tf->trace->has_tsc) {
1400 event->time.timestamp = ltt_get_uint32(LTT_GET_BO(t),
2896f39c 1401 pos);
54ecbf38 1402 /* 32 bits -> 64 bits tsc */
2896f39c 1403 /* note : still works for seek and non seek cases. */
54ecbf38 1404 if(event->time.timestamp < (0xFFFFFFFFULL&tf->buffer.tsc)) {
1405 tf->buffer.tsc = ((tf->buffer.tsc&0xFFFFFFFF00000000ULL)
1406 + 0x100000000ULL)
1407 | (guint64)event->time.timestamp;
b59cd2f8 1408 event->tsc = tf->buffer.tsc;
54ecbf38 1409 } else {
1410 /* no overflow */
1411 tf->buffer.tsc = (tf->buffer.tsc&0xFFFFFFFF00000000ULL)
1412 | (guint64)event->time.timestamp;
b59cd2f8 1413 event->tsc = tf->buffer.tsc;
54ecbf38 1414 }
2896f39c 1415
1416 event->event_time = ltt_interpolate_time(tf, event);
1417
54ecbf38 1418 pos += sizeof(uint32);
1419 } else {
1420 event->time.delta = ltt_get_uint32(LTT_GET_BO(tf),
2896f39c 1421 pos);
54ecbf38 1422 tf->buffer.tsc = 0;
b59cd2f8 1423 event->tsc = tf->buffer.tsc;
54ecbf38 1424
1425 event->event_time = ltt_time_add(tf->buffer.begin.timestamp,
1426 event->time_delta);
1427 pos += sizeof(uint32);
1428 }
1429
1430 event->facility_id = ltt_get_uint8(LTT_GET_BO(tf),
1431 tf->cur_event_pos);
1432 pos += sizeof(uint8);
1433
1434 event->event_id = ltt_get_uint8(LTT_GET_BO(tf),
1435 tf->cur_event_pos);
1436 pos += sizeof(uint8);
1437
1438 event->data = tf->cur_event_pos + EVENT_HEADER_SIZE;
1439
1440 event->data = pos;
1441
2896f39c 1442 return 0;
54ecbf38 1443}
1444
54ecbf38 1445
1446/****************************************************************************
1447 *Function name
1448 * map_block : map a block from the file
1449 *Input Params
1450 * lttdes : ltt trace file
1451 * whichBlock : the block which will be read
1452 *return value
1453 * 0 : success
1454 * EINVAL : lseek fail
1455 * EIO : can not read from the file
1456 ****************************************************************************/
1457
1458static int map_block(LttTracefile * tf, int block_num)
1459{
1460 struct ltt_block_start_header *header;
1461
1462 g_assert(block_num < tf->num_blocks);
1463
1464 if(tf->buffer.head != NULL)
1465 munmap(tf->buffer.head, tf->buf_size);
1466
1467 /* Multiple of pages aligned head */
1468 tf->buffer.head = mmap(0, tf->block_size, PROT_READ, tf->fd,
1469 (off_t)tf->block_size * (off_t)block_num);
1470
1471 if(tf->buffer.head == NULL) {
1472 perror("Error in allocating memory for buffer of tracefile %s\n", fileName);
1473 goto map_error;
1474 }
1475 g_assert(tf->buffer.head & (8-1) == 0); // make sure it's aligned.
1476
1477
1478 tf->buffer.index = block_num;
1479
1480 header = (struct ltt_block_start_header*)tf->buffer.head;
1481
1482 tf->buffer.begin.timestamp = ltt_get_uint64(LTT_GET_BO(tf),
1483 header->begin.timestamp)
1484 * NSEC_PER_USEC;
1485 tf->buffer.begin.cycle_count = ltt_get_uint64(LTT_GET_BO(tf),
1486 header->begin.cycle_count);
1487 tf->buffer.end.timestamp = ltt_get_uint64(LTT_GET_BO(tf),
1488 header->end.timestamp)
1489 * NSEC_PER_USEC;
1490 tf->buffer.end.cycle_count = ltt_get_uint64(LTT_GET_BO(tf),
1491 header->end.cycle_count);
1492 tf->buffer.lost_size = ltt_get_uint32(LTT_GET_BO(tf),
1493 header->lost_size);
1494
1495 tf->buffer.tsc = tf->buffer.begin.cycle_count;
b59cd2f8 1496 tf->event.tsc = tf->buffer.tsc;
54ecbf38 1497
1498 /* FIXME
1499 * eventually support variable buffer size : will need a partial pre-read of
1500 * the headers to create an index when we open the trace... eventually. */
1501 g_assert(tf->block_size == ltt_get_uint32(header->buf_size));
1502
1503 /* Now that the buffer is mapped, calculate the time interpolation for the
1504 * block. */
1505
1506 tf->buffer.nsecs_per_cycle = calc_nsecs_per_cycle(&tf->buffer);
1507
1508 /* Make the current event point to the beginning of the buffer :
1509 * it means that the event read must get the first event. */
1510 tf->event.tracefile = tf;
1511 tf->event.block = block_num;
1512 tf->event.offset = tf->buffer.head;
1513
1514 return 0;
1515
1516map_error:
1517 return -errno;
1518
1519}
1520
b59cd2f8 1521ssize_t ltt_get_event_size(LttTracefile *tf)
1522{
1523 ssize_t size = 0;
1524
1525 /* Specific handling of core events : necessary to read the facility control
1526 * tracefile. */
1527 if(unlikely(tf->event.facility_id == LTT_FACILITY_CORE)) {
1528 switch((enum ltt_core_events)tf->event.event_id) {
1529 case LTT_EVENT_FACILITY_LOAD:
1530 size = sizeof(struct LttFacilityLoad);
1531 break;
1532 case LTT_EVENT_FACILITY_UNLOAD:
1533 size = sizeof(struct LttFacilityUnload);
1534 break;
1535 case LTT_EVENT_STATE_DUMP_FACILITY_LOAD:
1536 size = sizeof(struct LttStateDumpFacilityLoad);
1537 break;
1538 case LTT_EVENT_HEARTBEAT:
1539 size = sizeof(TimeHeartbeat);
1540 break;
1541 default:
1542 g_warning("Error in getting event size : tracefile %s, "
1543 "unknown event id %hhu in core facility.",
1544 g_quark_to_string(tf->name),
1545 tf->event.event_id);
1546 goto event_id_error;
1547
1548 }
1549
1550 } else {
1551 LttFacility *f = ltt_trace_get_facility_by_num(tf->trace,
1552 tf->event.facility_id);
1553 LttEventType *event_type =
1554 ltt_facility_eventtype_get(f, tf->event.event_id);
1555 size = get_fields_offsets(tf, event_type, tf->event.data);
1556 }
1557
1558 return size;
1559
1560event_id_error:
1561 return -1;
1562}
1563
1564
54ecbf38 1565/* Take the tf current event offset and use the event facility id and event id
1566 * to figure out where is the next event offset.
1567 *
1568 * This is an internal function not aiming at being used elsewhere : it will
1569 * not jump over the current block limits. Please consider using
1570 * ltt_tracefile_read to do this.
1571 *
1572 * Returns 0 on success
1573 * ERANGE if we are at the end of the buffer.
2896f39c 1574 * ENOPROTOOPT if an error occured when getting the current event size.
54ecbf38 1575 */
1576static int ltt_seek_next_event(LttTracefile *tf)
1577{
2896f39c 1578 int ret = 0;
54ecbf38 1579 void *pos;
b59cd2f8 1580 ssize_t event_size;
54ecbf38 1581
1582 /* seek over the buffer header if we are at the buffer start */
1583 if(tf->event.offset == tf->buffer.head) {
1584 tf->event.offset += sizeof(struct ltt_block_start_header);
1585 goto found;
1586 }
1587
2896f39c 1588
1589 if(tf->event.offset == tf->buffer.head + tf->buffer.lost_size) {
1590 ret = ERANGE;
1591 goto found;
1592 }
54ecbf38 1593
1594 pos = tf->event.data;
1595
b59cd2f8 1596 event_size = ltt_get_event_size(tf);
1597 if(event_size < 0) goto error;
54ecbf38 1598
b59cd2f8 1599 pos += (size_t)event_size;
1600
54ecbf38 1601 tf->event.offset = pos;
1602
1603found:
2896f39c 1604 return ret;
54ecbf38 1605
1606error:
1607 g_error("Error in ltt_seek_next_event for tracefile %s",
1608 g_quark_to_string(tf->name));
2896f39c 1609 return ENOPROTOOPT;
54ecbf38 1610}
1611
1612
1613/*****************************************************************************
1614 *Function name
1615 * calc_nsecs_per_cycle : calculate nsecs per cycle for current block
1616 *Input Params
1617 * t : tracefile
1618 ****************************************************************************/
1619
1620static double calc_nsecs_per_cycle(LttTracefile * t)
1621{
1622 LttTime lBufTotalTime; /* Total time for this buffer */
1623 double lBufTotalNSec; /* Total time for this buffer in nsecs */
1624 LttCycleCount lBufTotalCycle;/* Total cycles for this buffer */
1625
1626 /* Calculate the total time for this buffer */
1627 lBufTotalTime = ltt_time_sub(
1628 ltt_get_time(t->buffer.end.timestamp),
1629 ltt_get_time(t->buffer.begin.timestamp));
1630
1631 /* Calculate the total cycles for this bufffer */
1632 lBufTotalCycle = t->buffer.end.cycle_count;
1633 lBufTotalCycle -= t->buffer.start.cycle_count;
1634
1635 /* Convert the total time to double */
1636 lBufTotalNSec = ltt_time_to_double(lBufTotalTime);
1637
1638 return lBufTotalNSec / (double)lBufTotalCycle;
1639
1640}
b59cd2f8 1641#if 0
1642void setFieldsOffset(LttTracefile *tf, LttEventType *evT,void *evD)
1643{
1644 LttField * rootFld = evT->root_field;
1645 // rootFld->base_address = evD;
1646
1647 if(likely(rootFld))
1648 rootFld->field_size = getFieldtypeSize(tf, evT->facility,
1649 evT, 0,0,rootFld, evD);
1650}
1651#endif //0
54ecbf38 1652
1653/*****************************************************************************
1654 *Function name
b59cd2f8 1655 * set_fields_offsets : set the precomputable offset of the fields
54ecbf38 1656 *Input params
1657 * tracefile : opened trace file
b59cd2f8 1658 * event_type : the event type
54ecbf38 1659 ****************************************************************************/
1660
b59cd2f8 1661void set_fields_offsets(LttTracefile *tf, LttEventType *event_type)
54ecbf38 1662{
b59cd2f8 1663 LttField *field = event_type->root_field;
54ecbf38 1664
b59cd2f8 1665 if(likely(field))
1666 preset_field_type_size(tf, event_type->facility, event_type, 0, 0,
1667 FIELD_FIXED, FIELD_FIXED,
1668 field);
1669
1670}
1671
1672
1673/*****************************************************************************
1674 *Function name
1675 * preset_field_type_size : set the fixed sizes of the field type
1676 *Input params
1677 * tf : tracefile
1678 * event_type : event type
1679 * offset_root : offset from the root
1680 * offset_parent : offset from the parent
1681 * fixed_root : Do we know a fixed offset to the root ?
1682 * fixed_parent : Do we know a fixed offset to the parent ?
1683 * field : field
1684 ****************************************************************************/
1685void preset_field_type_size(LttTracefile *tf, LttEventType *event_type,
1686 off_t offset_root, off_t offset_parent,
1687 enum field_status *fixed_root, enum field_status *fixed_parent,
1688 LttField *field)
1689{
1690 guint i;
1691 LttType *type;
1692
1693 g_assert(field->fixed_root == FIELD_UNKNOWN);
1694 g_assert(field->fixed_parent == FIELD_UNKNOWN);
1695 g_assert(field->fixed_size == FIELD_UNKNOWN);
1696
1697 type = field->field_type;
1698
1699 field->fixed_root = *fixed_root;
1700 if(field->fixed_root == FIELD_FIXED)
1701 field->offset_root = offset_root;
1702 else
1703 field->offset_root = 0;
1704
1705 field->fixed_parent = *fixed_parent;
1706 if(field->fixed_parent == FIELD_FIXED)
1707 field->offset_parent = offset_parent;
1708 else
1709 field->offset_parent = 0;
1710
1711
1712 switch(type->type_class) {
1713 case LTT_INT:
1714 case LTT_UINT:
1715 case LTT_FLOAT:
1716 case LTT_ENUM:
1717 field->field_size = (off_t) ltt_type_size(LTT_GET_BO(tf),
1718 event_type->facility, type);
1719 field->fixed_size = FIELD_FIXED;
1720 break;
1721 case LTT_POINTER:
1722 field->field_size = (off_t)event_type->facility->pointer_size;
1723 field->fixed_size = FIELD_FIXED;
1724 break;
1725 case LTT_LONG:
1726 case LTT_ULONG:
1727 field->field_size = (off_t)event_type->facility->pointer_size;
1728 field->fixed_size = FIELD_FIXED;
1729 break;
1730 case LTT_SIZE_T:
1731 case LTT_SSIZE_T:
1732 case LTT_OFF_T:
1733 field->field_size = (off_t)event_type->facility->size_t_size;
1734 field->fixed_size = FIELD_FIXED;
1735 break;
1736 case LTT_SEQUENCE:
1737 preset_field_type_size(tf, event_type->facility, event_type,
1738 0, 0,
1739 FIELD_VARIABLE, FIELD_VARIABLE,
1740 field->child[0]);
1741 field->fixed_size = FIELD_VARIABLE;
1742 field->field_size = 0;
1743 break;
1744 case LTT_STRING:
1745 field->fixed_size = FIELD_VARIABLE;
1746 field->field_size = 0;
1747 break;
1748 case LTT_ARRAY:
1749 preset_field_type_size(tf, event_type->facility, event_type,
1750 0, 0,
1751 FIELD_VARIABLE, FIELD_VARIABLE,
1752 field->child[0]);
1753 field->fixed_size = field->child[0]->fixed_size;
1754 if(field->fixed_size == FIELD_FIXED)
1755 field->field_size = type->element_number * field->child[0]->field_size;
1756 else
1757 field->field_size = 0;
1758 break;
1759 case LTT_STRUCT:
1760 size_t current_root_offset = field->offset_root;
1761 size_t current_offset = 0;
1762 enum field_status current_child_status = FIELD_FIXED;
1763 for(i=0;i<type->element_number;i++) {
1764 preset_field_type_size(tf, event_type->facility, event_type,
1765 current_root_offset, current_offset,
1766 fixed_root, &current_child_status,
1767 field->child[i]);
1768 if(current_child_status == FIELD_FIXED) {
1769 current_root_offset += field->child[i]->field_size;
1770 current_offset += field->child[i]->field_size;
1771 } else {
1772 current_root_offset = 0;
1773 current_offset = 0;
1774 }
1775 }
1776 if(current_child_status != FIELD_FIXED) {
1777 *fixed_parent = current_child_status;
1778 field->field_size = 0;
1779 field->fixed_size = current_child_status;
1780 } else {
1781 field->field_size = current_offset;
1782 field->fixed_size = FIELD_FIXED;
1783 }
1784 break;
1785 case LTT_UNION:
1786 size_t current_root_offset = field->offset_root;
1787 size_t current_offset = 0;
1788 size_t max_size = 0;
1789 enum field_status final_child_status = FIELD_FIXED;
1790 for(i=0;i<type->element_number;i++) {
1791 enum field_status current_root_child_status = FIELD_FIXED;
1792 enum field_status current_child_status = FIELD_FIXED;
1793 preset_field_type_size(tf, event_type->facility, event_type,
1794 current_root_offset, current_offset,
1795 &current_root_child_status, &current_child_status,
1796 field->child[i]);
1797 if(current_child_status != FIELD_FIXED)
1798 final_child_status = current_child_status;
1799 else
1800 max_size = max(max_size, field->child[i]->field_size);
1801 }
1802 if(final_child_status != FIELD_FIXED) {
1803 *fixed_root = final_child_status;
1804 *fixed_parent = final_child_status;
1805 field->field_size = 0;
1806 field->fixed_size = current_child_status;
1807 } else {
1808 field->field_size = max_size;
1809 field->fixed_size = FIELD_FIXED;
1810 }
1811 break;
1812 }
1813
1814}
1815
1816
1817/*****************************************************************************
1818 *Function name
1819 * get_field_type_size : set the fixed and dynamic sizes of the field type
1820 * from the data read.
1821 *Input params
1822 * tf : tracefile
1823 * event_type : event type
1824 * offset_root : offset from the root
1825 * offset_parent : offset from the parent
1826 * field : field
1827 * data : a pointer to the event data.
1828 *Returns the field type size.
1829 ****************************************************************************/
1830size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type,
1831 off_t offset_root, off_t offset_parent,
1832 LttField *field, void *data)
1833{
1834 size_t size = 0;
1835 guint i;
1836 LttType *type;
1837
1838 g_assert(field->fixed_root != FIELD_UNKNOWN);
1839 g_assert(field->fixed_parent != FIELD_UNKNOWN);
1840 g_assert(field->fixed_size != FIELD_UNKNOWN);
1841
1842 field->offset_root = offset_root;
1843 field->offset_parent = offset_parent;
1844
1845 type = field->field_type;
1846
1847 switch(type->type_class) {
1848 case LTT_INT:
1849 case LTT_UINT:
1850 case LTT_FLOAT:
1851 case LTT_ENUM:
1852 case LTT_POINTER:
1853 case LTT_LONG:
1854 case LTT_ULONG:
1855 case LTT_SIZE_T:
1856 case LTT_SSIZE_T:
1857 case LTT_OFF_T:
1858 g_assert(field->fixed_size == FIELD_FIXED);
1859 size = field->field_size;
1860 break;
1861 case LTT_SEQUENCE:
1862 gint seqnum = ltt_get_uint(LTT_GET_BO(tf),
1863 field->sequ_number_size,
1864 data + offset_root);
1865
1866 if(field->child[0]->fixed_size == FIELD_FIXED) {
1867 size = field->sequ_number_size +
1868 (seqnum * get_field_type_size(tf, event_type->facility, event_type,
1869 offset_root, offset_parent,
1870 field->child[0], data));
1871 } else {
1872 size += field->sequ_number_size;
1873 for(i=0;i<seqnum;i++) {
1874 size_t child_size;
1875 child_size = get_field_type_size(tf, event_type->facility,
1876 event_type,
1877 offset_root, offset_parent,
1878 field->child[0], data);
1879 offset_root += child_size;
1880 offset_parent += child_size;
1881 size += child_size;
1882 }
1883 }
1884 field->field_size = size;
1885 break;
1886 case LTT_STRING:
1887 size = strlen((char*)(data+offset_root)) + 1;// length + \0
1888 field->field_size = size;
1889 break;
1890 case LTT_ARRAY:
1891 if(field->fixed_size == FIELD_FIXED)
1892 size = field->field_size;
1893 else {
1894 for(i=0;i<seqnum;i++) {
1895 size_t child_size;
1896 child_size = get_field_type_size(tf, event_type->facility,
1897 event_type,
1898 offset_root, offset_parent,
1899 field->child[0], data);
1900 offset_root += child_size;
1901 offset_parent += child_size;
1902 size += child_size;
1903 }
1904 field->field_size = size;
1905 }
1906 break;
1907 case LTT_STRUCT:
1908 if(field->fixed_size == FIELD_FIXED)
1909 size = field->field_size;
1910 else {
1911 size_t current_root_offset = offset_root;
1912 size_t current_offset = 0;
1913 size_t child_size = 0;
1914 for(i=0;i<type->element_number;i++) {
1915 child_size = get_field_type_size(tf, event_type->facility,
1916 event_type, current_root_offset, current_offset,
1917 field->child[i], data);
1918 current_offset += child_size;
1919 current_root_offset += child_size;
1920
1921 }
1922 size = current_offset;
1923 field->field_size = size;
1924 }
1925 break;
1926 case LTT_UNION:
1927 if(field->fixed_size == FIELD_FIXED)
1928 size = field->field_size;
1929 else {
1930 size_t current_root_offset = field->offset_root;
1931 size_t current_offset = 0;
1932 for(i=0;i<type->element_number;i++) {
1933 size = get_field_type_size(tf, event_type->facility, event_type,
1934 current_root_offset, current_offset,
1935 field->child[i], data);
1936 size = max(size, field->child[i]->field_size);
1937 }
1938 field->field_size = size;
1939 }
1940 break;
1941 }
1942
1943 return size;
54ecbf38 1944}
1945
b59cd2f8 1946
1947
1948#if 0
54ecbf38 1949/*****************************************************************************
1950 *Function name
1951 * getFieldtypeSize: get the size of the field type (primitive type)
1952 *Input params
54ecbf38 1953 * evT : event type
1954 * offsetRoot : offset from the root
1955 * offsetParent : offset from the parrent
1956 * fld : field
1957 * evD : event data, it may be NULL
1958 *Return value
1959 * int : size of the field
1960 ****************************************************************************/
1961
b59cd2f8 1962static inline gint getFieldtypeSize(LttTracefile *tf,
54ecbf38 1963 LttEventType * evT, gint offsetRoot,
b59cd2f8 1964 gint offsetParent, LttField * fld, void *evD)
54ecbf38 1965{
1966 gint size, size1, element_number, i, offset1, offset2;
1967 LttType * type = fld->field_type;
1968
b59cd2f8 1969 /* This likely has been tested with gcov : half of them.. */
1970 if(unlikely(fld->field_fixed == 1)){
1971 /* tested : none */
1972 if(unlikely(fld == evT->root_field)) {
1973 size = fld->field_size;
1974 goto end_getFieldtypeSize;
54ecbf38 1975 }
b59cd2f8 1976 }
54ecbf38 1977
b59cd2f8 1978 /* From gcov profiling : half string, half struct, can we gain something
1979 * from that ? (Mathieu) */
1980 switch(type->type_class) {
1981 case LTT_ARRAY:
1982 element_number = (int) type->element_number;
1983 if(fld->field_fixed == -1){
1984 size = getFieldtypeSize(tf, evT, offsetRoot,
1985 0,fld->child[0], NULL);
1986 if(size == 0){ //has string or sequence
54ecbf38 1987 fld->field_fixed = 0;
b59cd2f8 1988 }else{
1989 fld->field_fixed = 1;
1990 size *= element_number;
54ecbf38 1991 }
b59cd2f8 1992 }else if(fld->field_fixed == 0){// has string or sequence
54ecbf38 1993 size = 0;
b59cd2f8 1994 for(i=0;i<element_number;i++){
1995 size += getFieldtypeSize(tf, evT, offsetRoot+size,size,
1996 fld->child[0], evD+size);
54ecbf38 1997 }
b59cd2f8 1998 }else size = fld->field_size;
1999 if(unlikely(!evD)){
54ecbf38 2000 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
2001 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
b59cd2f8 2002 }
54ecbf38 2003
b59cd2f8 2004 break;
2005
2006 case LTT_SEQUENCE:
2007 size1 = (int) ltt_type_size(fac, type);
2008 if(fld->field_fixed == -1){
2009 fld->sequ_number_size = size1;
2010 fld->field_fixed = 0;
2011 size = getFieldtypeSize(evT, offsetRoot,
2012 0,fld->child[0], NULL);
2013 fld->element_size = size;
2014 }else{//0: sequence
2015 element_number = getIntNumber(tf,size1,evD);
2016 type->element_number = element_number;
2017 if(fld->element_size > 0){
2018 size = element_number * fld->element_size;
2019 }else{//sequence has string or sequence
2020 size = 0;
54ecbf38 2021 for(i=0;i<element_number;i++){
b59cd2f8 2022 size += getFieldtypeSize(tf, evT,
2023 offsetRoot+size+size1,size+size1,
2024 fld->child[0], evD+size+size1);
54ecbf38 2025 }
b59cd2f8 2026 }
2027 size += size1;
2028 }
2029 if(unlikely(!evD)){
54ecbf38 2030 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
2031 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
b59cd2f8 2032 }
54ecbf38 2033
b59cd2f8 2034 break;
2035
2036 case LTT_STRING:
2037 size = 0;
2038 if(fld->field_fixed == -1){
2039 fld->field_fixed = 0;
2040 }else{//0: string
2041 /* Hope my implementation is faster than strlen (Mathieu) */
2042 char *ptr=(char*)evD;
2043 size = 1;
2044 /* from gcov : many many strings are empty, make it the common case.*/
2045 while(unlikely(*ptr != '\0')) { size++; ptr++; }
2046 //size = ptr - (char*)evD + 1; //include end : '\0'
2047 }
2048 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
2049 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
2050
2051 break;
2052
2053 case LTT_STRUCT:
2054 element_number = (int) type->element_number;
2055 size = 0;
2056 /* tested with gcov */
2057 if(unlikely(fld->field_fixed == -1)){
2058 offset1 = offsetRoot;
2059 offset2 = 0;
2060 for(i=0;i<element_number;i++){
2061 size1=getFieldtypeSize(tf, evT,offset1,offset2,
2062 fld->child[i], NULL);
2063 if(likely(size1 > 0 && size >= 0)){
2064 size += size1;
2065 if(likely(offset1 >= 0)) offset1 += size1;
2066 offset2 += size1;
2067 }else{
2068 size = -1;
2069 offset1 = -1;
2070 offset2 = -1;
2071 }
54ecbf38 2072 }
b59cd2f8 2073 if(unlikely(size == -1)){
2074 fld->field_fixed = 0;
2075 size = 0;
2076 }else fld->field_fixed = 1;
2077 }else if(likely(fld->field_fixed == 0)){
2078 offset1 = offsetRoot;
2079 offset2 = 0;
2080 for(i=0;unlikely(i<element_number);i++){
2081 size=getFieldtypeSize(tf, evT, offset1, offset2,
2082 fld->child[i], evD+offset2);
2083 offset1 += size;
2084 offset2 += size;
2085 }
2086 size = offset2;
2087 }else size = fld->field_size;
2088 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
2089 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
2090 break;
2091
2092 default:
2093 if(unlikely(fld->field_fixed == -1)){
2094 size = (int) ltt_type_size(LTT_GET_BO(tf), type);
2095 fld->field_fixed = 1;
2096 }else size = fld->field_size;
2097 if(unlikely(!evD)){
2098 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
2099 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
2100 }
2101 break;
54ecbf38 2102 }
2103
2104 fld->offset_root = offsetRoot;
2105 fld->offset_parent = offsetParent;
2106 fld->field_size = size;
2107
2108end_getFieldtypeSize:
2109
2110 return size;
2111}
b59cd2f8 2112#endif //0
54ecbf38 2113
2114/*****************************************************************************
2115 *Function name
b59cd2f8 2116 * get_int : get an integer number
54ecbf38 2117 *Input params
b59cd2f8 2118 * reverse_byte_order: must we reverse the byte order ?
54ecbf38 2119 * size : the size of the integer
b59cd2f8 2120 * ptr : the data pointer
54ecbf38 2121 *Return value
2122 * gint64 : a 64 bits integer
2123 ****************************************************************************/
2124
b59cd2f8 2125gint64 get_int(gboolean reverse_byte_order, gint size, void *data)
54ecbf38 2126{
b59cd2f8 2127 gint64 val;
54ecbf38 2128
2129 switch(size) {
b59cd2f8 2130 case 1: val = *((gint8*)data); break;
2131 case 2: val = ltt_get_int16(reverse_byte_order, data); break;
2132 case 4: val = ltt_get_int32(reverse_byte_order, data); break;
2133 case 8: val = ltt_get_int64(reverse_byte_order, data); break;
2134 default: val = ltt_get_int64(reverse_byte_order, data);
2135 g_critical("get_int : integer size %d unknown", size);
54ecbf38 2136 break;
2137 }
2138
b59cd2f8 2139 return val;
54ecbf38 2140}
54ecbf38 2141
b59cd2f8 2142/*****************************************************************************
2143 *Function name
2144 * get_uint : get an unsigned integer number
2145 *Input params
2146 * reverse_byte_order: must we reverse the byte order ?
2147 * size : the size of the integer
2148 * ptr : the data pointer
2149 *Return value
2150 * guint64 : a 64 bits unsigned integer
2151 ****************************************************************************/
2152
2153guint64 get_uint(gboolean reverse_byte_order, gint size, void *data)
2154{
2155 guint64 val;
2156
2157 switch(size) {
2158 case 1: val = *((gint8*)data); break;
2159 case 2: val = ltt_get_uint16(reverse_byte_order, data); break;
2160 case 4: val = ltt_get_uint32(reverse_byte_order, data); break;
2161 case 8: val = ltt_get_uint64(reverse_byte_order, data); break;
2162 default: val = ltt_get_uint64(reverse_byte_order, data);
2163 g_critical("get_uint : unsigned integer size %d unknown",
2164 size);
2165 break;
2166 }
2167
2168 return val;
2169}
2170
2171
54ecbf38 2172/* get the node name of the system */
2173
2174char * ltt_trace_system_description_node_name (LttSystemDescription * s)
2175{
2176 return s->node_name;
2177}
2178
2179
2180/* get the domain name of the system */
2181
2182char * ltt_trace_system_description_domain_name (LttSystemDescription * s)
2183{
2184 return s->domain_name;
2185}
2186
2187
2188/* get the description of the system */
2189
2190char * ltt_trace_system_description_description (LttSystemDescription * s)
2191{
2192 return s->description;
2193}
2194
2195
2196/* get the start time of the trace */
2197
2198LttTime ltt_trace_system_description_trace_start_time(LttSystemDescription *s)
2199{
2200 return s->trace_start;
2201}
2202
2203
2204LttTracefile *ltt_tracefile_new()
2205{
2206 return g_new(LttTracefile, 1);
2207}
2208
2209void ltt_tracefile_destroy(LttTracefile *tf)
2210{
2211 g_free(tf);
2212}
2213
2214void ltt_tracefile_copy(LttTracefile *dest, const LttTracefile *src)
2215{
2216 *dest = *src;
2217}
2218
2219/* Before library loading... */
2220
2221static void __attribute__((constructor)) init(void)
2222{
2223 LTT_FACILITY_NAME_HEARTBEAT = g_quark_from_string("heartbeat");
2224 LTT_EVENT_NAME_HEARTBEAT = g_quark_from_string("heartbeat");
2225
2226 LTT_TRACEFILE_NAME_FACILITIES = g_quark_from_string("control/facilities");
2227}
2228
This page took 0.107683 seconds and 4 git commands to generate.