From eed2ef37f908daf7b3f884b5d8f91dad03f10526 Mon Sep 17 00:00:00 2001 From: compudj Date: Fri, 19 Aug 2005 16:46:52 +0000 Subject: [PATCH] lttv and lib ltt new compiles git-svn-id: http://ltt.polymtl.ca/svn@1017 04897980-b3bd-0310-b5e0-8ef037075253 --- ltt/branches/poly/ltt-newlib/ltt-private.h | 386 --- ltt/branches/poly/ltt-newlib/tracefile.c | 2228 ----------------- .../{ltt-newlib => ltt-oldlib}/Makefile.am | 0 .../{ltt-newlib => ltt-oldlib}/compiler.h | 0 .../convert/LTTTypes.h | 0 .../convert/LinuxEvents.h | 0 .../convert/Makefile.am | 0 .../{ltt-newlib => ltt-oldlib}/convert/README | 0 .../convert/convert.c | 0 .../convert/core.xml | 0 .../convert/sysInfo | 0 .../poly/{ltt-newlib => ltt-oldlib}/crc32.tab | 0 .../poly/{ltt-newlib => ltt-oldlib}/event.c | 224 +- .../poly/{ltt-newlib => ltt-oldlib}/event.h | 3 +- .../{ltt-newlib => ltt-oldlib}/facility.c | 211 +- .../{ltt-newlib => ltt-oldlib}/facility.h | 10 +- ltt/branches/poly/ltt-oldlib/ltt-private.h | 252 ++ .../{ltt-newlib => ltt-oldlib}/ltt-types.h | 0 .../poly/{ltt-newlib => ltt-oldlib}/ltt.h | 5 +- .../poly/{ltt-newlib => ltt-oldlib}/parser.c | 0 .../poly/{ltt-newlib => ltt-oldlib}/parser.h | 0 .../poly/{ltt-newlib => ltt-oldlib}/time.h | 0 .../poly/{ltt-newlib => ltt-oldlib}/trace.h | 21 +- ltt/branches/poly/ltt-oldlib/tracefile.c | 1754 +++++++++++++ .../poly/{ltt-newlib => ltt-oldlib}/type.c | 91 +- .../poly/{ltt-newlib => ltt-oldlib}/type.h | 8 +- ltt/branches/poly/ltt/event.c | 182 +- ltt/branches/poly/ltt/event.h | 29 +- ltt/branches/poly/ltt/ltt-private.h | 10 +- ltt/branches/poly/ltt/trace.h | 4 +- ltt/branches/poly/ltt/tracefile.c | 192 +- ltt/branches/poly/lttv/lttv/batchtest.c | 228 +- ltt/branches/poly/lttv/lttv/filter.c | 9 +- ltt/branches/poly/lttv/lttv/lttv.h | 3 + ltt/branches/poly/lttv/lttv/state.c | 578 +++-- ltt/branches/poly/lttv/lttv/state.h | 39 +- ltt/branches/poly/lttv/lttv/stats.c | 222 +- ltt/branches/poly/lttv/lttv/tracecontext.c | 265 +- ltt/branches/poly/lttv/lttv/tracecontext.h | 31 +- 39 files changed, 3543 insertions(+), 3442 deletions(-) delete mode 100644 ltt/branches/poly/ltt-newlib/ltt-private.h delete mode 100644 ltt/branches/poly/ltt-newlib/tracefile.c rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/Makefile.am (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/compiler.h (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/convert/LTTTypes.h (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/convert/LinuxEvents.h (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/convert/Makefile.am (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/convert/README (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/convert/convert.c (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/convert/core.xml (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/convert/sysInfo (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/crc32.tab (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/event.c (73%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/event.h (98%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/facility.c (77%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/facility.h (89%) create mode 100644 ltt/branches/poly/ltt-oldlib/ltt-private.h rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/ltt-types.h (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/ltt.h (96%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/parser.c (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/parser.h (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/time.h (100%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/trace.h (91%) create mode 100644 ltt/branches/poly/ltt-oldlib/tracefile.c rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/type.c (86%) rename ltt/branches/poly/{ltt-newlib => ltt-oldlib}/type.h (93%) diff --git a/ltt/branches/poly/ltt-newlib/ltt-private.h b/ltt/branches/poly/ltt-newlib/ltt-private.h deleted file mode 100644 index 4c86aaf0..00000000 --- a/ltt/branches/poly/ltt-newlib/ltt-private.h +++ /dev/null @@ -1,386 +0,0 @@ -/* This file is part of the Linux Trace Toolkit viewer - * Copyright (C) 2003-2004 Xiangxiu Yang - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifndef LTT_PRIVATE_H -#define LTT_PRIVATE_H - -#include -#include -#include - -#define LTT_MAGIC_NUMBER 0x00D6B7ED -#define LTT_REV_MAGIC_NUMBER 0xEDB7D600 - -#define NSEC_PER_USEC 1000 - -#define LTT_PACKED_STRUCT __attribute__ ((packed)) - -#define NUM_FACILITIES 256 - -/* Hardcoded facilities */ -#define LTT_FACILITY_CORE 0 - -/* Hardcoded core events */ -enum ltt_core_events { - LTT_EVENT_FACILITY_LOAD, - LTT_EVENT_FACILITY_UNLOAD, - LTT_EVENT_STATE_DUMP_FACILITY_LOAD, - LTT_EVENT_HEARTBEAT -}; - - -#if 0 -/* enumeration definition */ - -typedef enum _BuildinEvent{ - TRACE_FACILITY_LOAD = 0, - TRACE_BLOCK_START = 17, - TRACE_BLOCK_END = 18, - TRACE_TIME_HEARTBEAT= 19 -} BuildinEvent; - - -/* structure definition */ - -typedef struct _FacilityLoad{ - gchar * name; - LttChecksum checksum; - guint32 base_code; -} LTT_PACKED_STRUCT FacilityLoad; - -typedef struct _BlockStart { - LttTime time; //Time stamp of this block - LttCycleCount cycle_count; //cycle count of the event - guint32 block_id; //block id -} LTT_PACKED_STRUCT BlockStart; - -typedef struct _BlockEnd { - LttTime time; //Time stamp of this block - LttCycleCount cycle_count; //cycle count of the event - guint32 block_id; //block id -} LTT_PACKED_STRUCT BlockEnd; -#endif //0 - - -typedef guint8 uint8_t; -typedef guint16 uint16_t; -typedef guint32 uint32_t; -typedef guint64 uint64_t; - -/* Hardcoded facility load event : this plus an following "name" string */ -struct LttFacilityLoad { - guint32 checksum; - guint32 id; - guint32 long_size; - guint32 pointer_size; - guint32 size_t_size; - guint32 alignment; -}; - -struct LttFacilityUnload { - guint32 id; -}; - -struct LttStateDumpFacilityLoad { - guint32 checksum; - guint32 id; - guint32 long_size; - guint32 pointer_size; - guint32 size_t_size; - guint32 alignment; -}; - - - -typedef struct _TimeHeartbeat { - LttTime time; //Time stamp of this block - uint64_t cycle_count; //cycle count of the event -} LTT_PACKED_STRUCT TimeHeartbeat; - -struct ltt_event_header_hb { - uint32_t timestamp; - unsigned char facility_id; - unsigned char event_id; - uint16_t event_size; -} __attribute((aligned(8))); - -struct ltt_event_header_nohb { - uint64_t timestamp; - unsigned char facility_id; - unsigned char event_id; - uint16_t event_size; -} __attribute((aligned(8))); - -struct ltt_trace_header { - uint32_t magic_number; - uint32_t arch_type; - uint32_t arch_variant; - uint8_t arch_size; - //uint32_t system_type; - uint8_t major_version; - uint8_t minor_version; - uint8_t flight_recorder; - uint8_t has_heartbeat; - uint8_t has_alignment; /* Event header alignment */ - uint8_t has_tsc; -} __attribute((aligned(8))); - - -struct ltt_block_start_header { - struct { - struct timeval timestamp; - uint64_t cycle_count; - } begin; - struct { - struct timeval timestamp; - uint64_t cycle_count; - } end; - uint32_t lost_size; /* Size unused at the end of the buffer */ - uint32_t buf_size; /* The size of this sub-buffer */ - struct ltt_trace_header trace; -} __attribute((aligned(8))); - - -struct _LttType{ - GQuark type_name; //type name if it is a named type - GQuark element_name; //elements name of the struct - gchar * fmt; - unsigned int size; - LttTypeEnum type_class; //which type - gchar ** enum_strings; //for enum labels - struct _LttType ** element_type; //for array, sequence and struct - unsigned element_number; //the number of elements - //for enum, array, sequence and structure -}; - -struct _LttEventType{ - GQuark name; - gchar * description; - guint index; //id of the event type within the facility - LttFacility * facility; //the facility that contains the event type - LttField * root_field; //root field -}; - -/* Structure LttEvent and LttEventPosition must begin with the _exact_ same - * fields in the exact same order. LttEventPosition is a parent of LttEvent. */ -struct _LttEvent{ - - /* Begin of LttEventPosition fields */ - LttTracefile *tracefile; - unsigned int block; - void *offset; - - /* Timekeeping */ - uint64_t tsc; /* Current timestamp counter */ - - /* End of LttEventPosition fields */ - - union { /* choice by trace has_tsc */ - guint32 timestamp; /* truncated timestamp */ - guint32 delta; - } time; - - unsigned char facility_id; /* facility ID are never reused. */ - unsigned char event_id; - - LttTime event_time; - - void * data; //event data - - int count; //the number of overflow of cycle count - gint64 overflow_nsec; //precalculated nsec for overflows -}; - -struct _LttEventPosition{ - LttTracefile *tracefile; - unsigned int block; - void *offset; - - /* Timekeeping */ - uint64_t tsc; /* Current timestamp counter */ -}; - - -enum field_status { FIELD_UNKNOWN, FIELD_VARIABLE, FIELD_FIXED }; - -struct _LttField{ - //guint field_pos; //field position within its parent - LttType * field_type; //field type, if it is root field - //then it must be struct type - - off_t offset_root; //offset from the root, -1:uninitialized - enum field_status fixed_root; //offset fixed according to the root - //-1:uninitialized, 0:unfixed, 1:fixed - off_t offset_parent; //offset from the parent,-1:uninitialized - enum field_status fixed_parent; //offset fixed according to its parent - //-1:uninitialized, 0:unfixed, 1:fixed - // void * base_address; //base address of the field ???? - - guint field_size; // //>0: size of the field, - // //0 : uncertain - // //-1: uninitialize - enum field_status fixed_size; - - /* for sequence */ - gint sequ_number_size; //the size of unsigned used to save the - //number of elements in the sequence - - gint element_size; //the element size of the sequence - //int field_fixed; //0: field has string or sequence - //1: field has no string or sequenc - //-1: uninitialize - - struct _LttField * parent; - struct _LttField ** child; //for array, sequence, struct and union: - //list of fields, it may have only one - //field if the element is not a struct or - //union - unsigned current_element; //which element is currently processed - // Used for sequences and arrays. -}; - - -struct _LttFacility{ - LttTrace *trace; - //gchar * name; //facility name - GQuark name; - guint32 checksum; //checksum of the facility - guint32 id; //id of the facility - - guint32 pointer_size; - guint32 size_t_size; - guint32 alignment; - - - //LttEventType ** events; //array of event types - //unsigned int event_number; //number of events in the facility - //LttType ** named_types; - //unsigned int named_types_number; - - GArray *events; - GData *events_by_name; - // GArray *named_types; - //GData *named_types_by_name; - GData *named_types; - - unsigned char exists; /* 0 does not exist, 1 exists */ -}; - -typedef struct _LttBuffer { - void * head; - unsigned int index; - - struct { - struct timeval timestamp; - uint64_t cycle_count; - } begin; - struct { - struct timeval timestamp; - uint64_t cycle_count; - } end; - uint32_t lost_size; /* Size unused at the end of the buffer */ - - /* Timekeeping */ - uint64_t tsc; /* Current timestamp counter */ - double nsecs_per_cycle; -} LttBuffer; - -struct _LttTracefile{ - gboolean cpu_online; //is the cpu online ? - GQuark name; //tracefile name - guint cpu_num; //cpu number of the tracefile - LttTrace * trace; //trace containing the tracefile - int fd; //file descriptor - off_t file_size; //file size - unsigned block_size; //block_size - unsigned int num_blocks; //number of blocks in the file - gboolean reverse_bo; //must we reverse byte order ? - - /* Current event */ - LttEvent event; //Event currently accessible in the trace - - /* Current block */ - LttBuffer buffer; //current buffer - guint32 buf_size; /* The size of blocks */ - - /* Time flow */ - //unsigned int count; //the number of overflow of cycle count - //double nsec_per_cycle; //Nsec per cycle - //TimeHeartbeat * last_heartbeat; //last heartbeat - - //LttCycleCount cycles_per_nsec_reciprocal; // Optimisation for speed - //void * last_event_pos; - - //LttTime prev_block_end_time; //the end time of previous block - //LttTime prev_event_time; //the time of the previous event - //LttCycleCount pre_cycle_count; //previous cycle count of the event -}; - -struct _LttTrace{ - GQuark pathname; //the pathname of the trace - //LttSystemDescription * system_description;//system description - - GArray *facilities_by_num; /* fac_id as index in array */ - GData *facilities_by_name; /* fac name (GQuark) as index */ - /* Points to array of fac_id of all the - * facilities that has this name. */ - - guint8 ltt_major_version; - guint8 ltt_minor_version; - guint8 flight_recorder; - guint8 has_heartbeat; - // guint8 alignment; - guint8 has_tsc; - - GData *tracefiles; //tracefiles groups -}; - -/* The characteristics of the system on which the trace was obtained - is described in a LttSystemDescription structure. */ - -struct _LttSystemDescription { - gchar *description; - gchar *node_name; - gchar *domain_name; - unsigned nb_cpu; - LttArchSize size; - LttArchEndian endian; - gchar *kernel_name; - gchar *kernel_release; - gchar *kernel_version; - gchar *machine; - gchar *processor; - gchar *hardware_platform; - gchar *operating_system; - LttTime trace_start; - LttTime trace_end; -}; - -/***************************************************************************** - macro for size of some data types - *****************************************************************************/ -// alignment -> dynamic! - -//#define TIMESTAMP_SIZE sizeof(guint32) -//#define EVENT_ID_SIZE sizeof(guint16) -//#define EVENT_HEADER_SIZE (TIMESTAMP_SIZE + EVENT_ID_SIZE) - -#define LTT_GET_BO(t) ((t)->reverse_bo) - - -#endif /* LTT_PRIVATE_H */ diff --git a/ltt/branches/poly/ltt-newlib/tracefile.c b/ltt/branches/poly/ltt-newlib/tracefile.c deleted file mode 100644 index 0fce811c..00000000 --- a/ltt/branches/poly/ltt-newlib/tracefile.c +++ /dev/null @@ -1,2228 +0,0 @@ -/* This file is part of the Linux Trace Toolkit viewer - * Copyright (C) 2005 Mathieu Desnoyers - * - * Complete rewrite from the original version made by XangXiu Yang. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License Version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// For realpath -#include -#include - - -#include "parser.h" -#include -#include "ltt-private.h" -#include -#include -#include -#include -#include - - -/* Facility names used in this file */ - -GQuark LTT_FACILITY_NAME_HEARTBEAT, - LTT_EVENT_NAME_HEARTBEAT; - -#ifndef g_open -#define g_open open -#endif - - -#define __UNUSED__ __attribute__((__unused__)) - -#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) -#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) - -#define g_close close - -/* obtain the time of an event */ - -static inline LttTime getEventTime(LttTracefile * tf); - - -/* set the offset of the fields belonging to the event, - need the information of the archecture */ -void set_fields_offsets(LttTracefile *tf, LttEventType *event_type); -size_t get_fields_offsets(LttTracefile *tf, LttEventType *event_type, void *data); - -/* get the size of the field type according to - * The facility size information. */ -static inline void preset_field_type_size(LttTracefile *tf, - LttEventType *event_type, - off_t offset_root, off_t offset_parent, - enum field_status *fixed_root, enum field_status *fixed_parent, - LttField *field) - - -static inline size_t get_field_type_size(LttTracefile *tf, - LttEventType *event_type, - off_t offset_root, off_t offset_parent, - LttField *field, void *data) - - -/* map a fixed size or a block information from the file (fd) */ -int map_block(LttTracefile * tf, unsigned int block_num); - -/* calculate nsec per cycles for current block */ -static double calc_nsecs_per_cycle(LttTracefile * t); - -/* go to the next event */ -static int ltt_seek_next_event(LttTracefile *tf); - -/* Functions to parse system.xml file (using glib xml parser) */ -static void parser_start_element (GMarkupParseContext __UNUSED__ *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - int i=0; - LttSystemDescription* des = (LttSystemDescription* )user_data; - if(strcmp("system", element_name)){ - *error = g_error_new(G_MARKUP_ERROR, - G_LOG_LEVEL_WARNING, - "This is not system.xml file"); - return; - } - - while(attribute_names[i]){ - if(strcmp("node_name", attribute_names[i])==0){ - des->node_name = g_strdup(attribute_values[i]); - }else if(strcmp("domainname", attribute_names[i])==0){ - des->domain_name = g_strdup(attribute_values[i]); - }else if(strcmp("cpu", attribute_names[i])==0){ - des->nb_cpu = atoi(attribute_values[i]); - }else if(strcmp("arch_size", attribute_names[i])==0){ - if(strcmp(attribute_values[i],"LP32") == 0) des->size = LTT_LP32; - else if(strcmp(attribute_values[i],"ILP32") == 0) des->size = LTT_ILP32; - else if(strcmp(attribute_values[i],"LP64") == 0) des->size = LTT_LP64; - else if(strcmp(attribute_values[i],"ILP64") == 0) des->size = LTT_ILP64; - else if(strcmp(attribute_values[i],"UNKNOWN") == 0) des->size = LTT_UNKNOWN; - }else if(strcmp("endian", attribute_names[i])==0){ - if(strcmp(attribute_values[i],"LITTLE_ENDIAN") == 0) - des->endian = LTT_LITTLE_ENDIAN; - else if(strcmp(attribute_values[i],"BIG_ENDIAN") == 0) - des->endian = LTT_BIG_ENDIAN; - }else if(strcmp("kernel_name", attribute_names[i])==0){ - des->kernel_name = g_strdup(attribute_values[i]); - }else if(strcmp("kernel_release", attribute_names[i])==0){ - des->kernel_release = g_strdup(attribute_values[i]); - }else if(strcmp("kernel_version", attribute_names[i])==0){ - des->kernel_version = g_strdup(attribute_values[i]); - }else if(strcmp("machine", attribute_names[i])==0){ - des->machine = g_strdup(attribute_values[i]); - }else if(strcmp("processor", attribute_names[i])==0){ - des->processor = g_strdup(attribute_values[i]); - }else if(strcmp("hardware_platform", attribute_names[i])==0){ - des->hardware_platform = g_strdup(attribute_values[i]); - }else if(strcmp("operating_system", attribute_names[i])==0){ - des->operating_system = g_strdup(attribute_values[i]); - }else if(strcmp("ltt_major_version", attribute_names[i])==0){ - des->ltt_major_version = atoi(attribute_values[i]); - }else if(strcmp("ltt_minor_version", attribute_names[i])==0){ - des->ltt_minor_version = atoi(attribute_values[i]); - }else if(strcmp("ltt_block_size", attribute_names[i])==0){ - des->ltt_block_size = atoi(attribute_values[i]); - }else{ - *error = g_error_new(G_MARKUP_ERROR, - G_LOG_LEVEL_WARNING, - "Not a valid attribute"); - return; - } - i++; - } -} - -static void parser_characters (GMarkupParseContext __UNUSED__ *context, - const gchar *text, - gsize __UNUSED__ text_len, - gpointer user_data, - GError __UNUSED__ **error) -{ - LttSystemDescription* des = (LttSystemDescription* )user_data; - des->description = g_strdup(text); -} - -static inline LttFacility *ltt_trace_get_facility_by_num(LttTrace *t, - guint num) -{ - g_assert(num < t->facilities_by_num->len); - - return &g_array_index(t->facilities_by_num, LttFacility, num); - -} - - -/***************************************************************************** - *Function name - * ltt_tracefile_open : open a trace file, construct a LttTracefile - *Input params - * t : the trace containing the tracefile - * fileName : path name of the trace file - * tf : the tracefile structure - *Return value - * : 0 for success, -1 otherwise. - ****************************************************************************/ - -int ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf) -{ - struct stat lTDFStat; /* Trace data file status */ - struct ltt_block_start_header *header; - - //open the file - tf->name = g_quark_from_string(fileName); - tf->trace = t; - tf->fd = g_open(fileName, O_RDONLY, 0); - if(tf->fd < 0){ - g_warning("Unable to open input data file %s\n", fileName); - goto end; - } - - // Get the file's status - if(fstat(tf->fd, &lTDFStat) < 0){ - g_warning("Unable to get the status of the input data file %s\n", fileName); - goto close_file; - } - - // Is the file large enough to contain a trace - if(lTDFStat.st_size < (off_t)(sizeof(BlockStart))){ - g_print("The input data file %s does not contain a trace\n", fileName); - goto close_file; - } - - /* Temporarily map the buffer start header to get trace information */ - /* Multiple of pages aligned head */ - tf->buffer.head = mmap(0, sizeof(struct ltt_block_start_header), PROT_READ, - tf->fd, 0); - if(tf->buffer == NULL) { - perror("Error in allocating memory for buffer of tracefile %s\n", fileName); - goto close_file; - } - g_assert(tf->buffer.head & (8-1) == 0); // make sure it's aligned. - - header = (struct ltt_block_start_header*)tf->buffer.head; - - if(header->traceset.magic_number == LTT_MAGIC_NUMBER) - tf->reverse_bo = 0; - else if(header->traceset.magic_number == LTT_REV_MAGIC_NUMBER) - tf->reverse_bo = 1; - else /* invalid magic number, bad tracefile ! */ - goto unmap_file; - - //store the size of the file - tf->file_size = lTDFStat.st_size; - tf->block_size = header->buf_size; - tf->block_number = tf->file_size / tf->block_size; - - vfree(tf->buffer.head); - tf->buffer.head = NULL; - - //read the first block - if(map_block(tf,0)) { - perror("Cannot map block %u for tracefile %s\n", 0, fileName); - goto close_file; - } - - return 0; - - /* Error */ -unmap_file: - munmap(tf->buffer.head, sizeof(struct ltt_block_start_header)); -close_file: - g_close(tf->fd); -end: - return -1; -} - - -/***************************************************************************** - *Open control and per cpu tracefiles - ****************************************************************************/ - -void ltt_tracefile_open_cpu(LttTrace *t, gchar * tracefile_name) -{ - LttTracefile * tf; - tf = ltt_tracefile_open(t,tracefile_name); - if(!tf) return; - t->per_cpu_tracefile_number++; - g_ptr_array_add(t->per_cpu_tracefiles, tf); -} - -gint ltt_tracefile_open_control(LttTrace *t, gchar * control_name) -{ - LttTracefile * tf; - LttEvent ev; - LttFacility * f; - void * pos; - FacilityLoad fLoad; - unsigned int i; - - tf = ltt_tracefile_open(t,control_name); - if(!tf) { - g_warning("ltt_tracefile_open_control : bad file descriptor"); - return -1; - } - t->control_tracefile_number++; - g_ptr_array_add(t->control_tracefiles,tf); - - //parse facilities tracefile to get base_id - if(strcmp(&control_name[strlen(control_name)-10],"facilities") ==0){ - while(1){ - if(!ltt_tracefile_read(tf,&ev)) return 0; // end of file - - if(ev.event_id == TRACE_FACILITY_LOAD){ - pos = ev.data; - fLoad.name = (gchar*)pos; - fLoad.checksum = *(LttChecksum*)(pos + strlen(fLoad.name)); - fLoad.base_code = *(guint32 *)(pos + strlen(fLoad.name) + sizeof(LttChecksum)); - - for(i=0;ifacility_number;i++){ - f = (LttFacility*)g_ptr_array_index(t->facilities,i); - if(strcmp(f->name,fLoad.name)==0 && fLoad.checksum==f->checksum){ - f->base_id = fLoad.base_code; - break; - } - } - if(i==t->facility_number) { - g_warning("Facility: %s, checksum: %u is not found", - fLoad.name,(unsigned int)fLoad.checksum); - return -1; - } - }else if(ev.event_id == TRACE_BLOCK_START){ - continue; - }else if(ev.event_id == TRACE_BLOCK_END){ - break; - }else { - g_warning("Not valid facilities trace file"); - return -1; - } - } - } - return 0; -} - -/***************************************************************************** - *Function name - * ltt_tracefile_close: close a trace file, - *Input params - * t : tracefile which will be closed - ****************************************************************************/ - -void ltt_tracefile_close(LttTracefile *t) -{ - if(t->buffer.head != NULL) - munmap(t->buffer.head, t->buf_size); - g_close(t->fd); -} - - -/***************************************************************************** - *Get system information - ****************************************************************************/ -gint getSystemInfo(LttSystemDescription* des, gchar * pathname) -{ - int fd; - GIOChannel *iochan; - gchar *buf = NULL; - gsize length; - - GMarkupParseContext * context; - GError * error = NULL; - GMarkupParser markup_parser = - { - parser_start_element, - NULL, - parser_characters, - NULL, /* passthrough */ - NULL /* error */ - }; - - fd = g_open(pathname, O_RDONLY, 0); - if(fd == -1){ - g_warning("Can not open file : %s\n", pathname); - return -1; - } - - iochan = g_io_channel_unix_new(fd); - - context = g_markup_parse_context_new(&markup_parser, 0, des,NULL); - - //while(fgets(buf,DIR_NAME_SIZE, fp) != NULL){ - while(g_io_channel_read_line(iochan, &buf, &length, NULL, &error) - != G_IO_STATUS_EOF) { - - if(error != NULL) { - g_warning("Can not read xml file: \n%s\n", error->message); - g_error_free(error); - } - if(!g_markup_parse_context_parse(context, buf, length, &error)){ - if(error != NULL) { - g_warning("Can not parse xml file: \n%s\n", error->message); - g_error_free(error); - } - g_markup_parse_context_free(context); - - g_io_channel_shutdown(iochan, FALSE, &error); /* No flush */ - if(error != NULL) { - g_warning("Can not close file: \n%s\n", error->message); - g_error_free(error); - } - - close(fd); - return -1; - } - } - g_markup_parse_context_free(context); - - g_io_channel_shutdown(iochan, FALSE, &error); /* No flush */ - if(error != NULL) { - g_warning("Can not close file: \n%s\n", error->message); - g_error_free(error); - } - - g_close(fd); - - g_free(buf); - return 0; -} - -/***************************************************************************** - *The following functions get facility/tracefile information - ****************************************************************************/ - -gint getFacilityInfo(LttTrace *t, gchar* eventdefs) -{ - GDir * dir; - const gchar * name; - unsigned int i,j; - LttFacility * f; - LttEventType * et; - gchar fullname[DIR_NAME_SIZE]; - GError * error = NULL; - - dir = g_dir_open(eventdefs, 0, &error); - - if(error != NULL) { - g_warning("Can not open directory: %s, %s\n", eventdefs, error->message); - g_error_free(error); - return -1; - } - - while((name = g_dir_read_name(dir)) != NULL){ - if(!g_pattern_match_simple("*.xml", name)) continue; - strcpy(fullname,eventdefs); - strcat(fullname,name); - ltt_facility_open(t,fullname); - } - g_dir_close(dir); - - for(j=0;jfacility_number;j++){ - f = (LttFacility*)g_ptr_array_index(t->facilities, j); - for(i=0; ievent_number; i++){ - et = f->events[i]; - setFieldsOffset(NULL, et, NULL, t); - } - } - return 0; -} - -/***************************************************************************** - *A trace is specified as a pathname to the directory containing all the - *associated data (control tracefiles, per cpu tracefiles, event - *descriptions...). - * - *When a trace is closed, all the associated facilities, types and fields - *are released as well. - */ - - -/**************************************************************************** - * get_absolute_pathname - * - * return the unique pathname in the system - * - * MD : Fixed this function so it uses realpath, dealing well with - * forgotten cases (.. were not used correctly before). - * - ****************************************************************************/ -void get_absolute_pathname(const gchar *pathname, gchar * abs_pathname) -{ - abs_pathname[0] = '\0'; - - if ( realpath (pathname, abs_pathname) != NULL) - return; - else - { - /* error, return the original path unmodified */ - strcpy(abs_pathname, pathname); - return; - } - return; -} - -/* Search for something like : .*_.* - * - * The left side is the name, the right side is the number. - */ - -int get_tracefile_name_number(const gchar *raw_name, - GQuark *name, - guint *num) -{ - guint raw_name_len = strlen(raw_name); - gchar char_name[PATH_MAX] - gchar *digit_begin; - int i; - int underscore_pos; - long int cpu_num; - gchar *endptr; - - for(i=raw_name_len-1;i>=0;i--) { - if(raw_name[i] == '_') break; - } - if(i==0) /* Either not found or name length is 0 */ - return -1; - underscore_pos = i; - - cpu_num = strtol(raw_name+underscore_pos+1, &endptr, 10); - - if(endptr == raw_name+underscore_pos+1) - return -1; /* No digit */ - if(cpu_num == LONG_MIN || cpu_num == LONG_MAX) - return -1; /* underflow / overflow */ - - char_name = strncpy(char_name, raw_name, underscore_pos); - - *name = g_quark_from_string(char_name); - *num = cpu_num; - - return 0; -} - - -void ltt_tracefile_group_destroy(gpointer data) -{ - GArray *group = (GArray *)data; - int i; - LttTracefile *tf; - - for(i=0; ilen; i++) { - tf = &g_array_index (group, LttTracefile, i); - if(tf->cpu_online) - ltt_tracefile_close(tf); - } - g_array_free(group, TRUE); -} - -gboolean ltt_tracefile_group_has_cpu_online(gpointer data) -{ - GArray *group = (GArray *)data; - int i; - LttTracefile *tf; - - for(i=0; ilen; i++) { - tf = &g_array_index (group, LttTracefile, i); - if(tf->cpu_online) return 1; - } - return 0; -} - - -/* Open each tracefile under a specific directory. Put them in a - * GData : permits to access them using their tracefile group pathname. - * i.e. access control/modules tracefile group by index : - * "control/module". - * - * A tracefile group is simply an array where all the per cpu tracefiles sits. - */ - -static int open_tracefiles(LttTrace *trace, char *root_path, GData *tracefiles) -{ - DIR *dir = opendir(root_path); - struct dirent *entry; - struct stat stat_buf; - int ret; - char path[PATH_MAX]; - int path_len; - char *path_ptr; - - if(channel_dir == NULL) { - perror(subchannel_name); - return ENOENT; - } - - strncpy(path, root_path, PATH_MAX-1); - path_len = strlen(path); - path[path_len] = '/'; - path_len++; - path_ptr = path + path_len; - - while((entry = readdir(channel_dir)) != NULL) { - - if(entry->d_name[0] == '.') continue; - - strncpy(path_ptr, entry->d_name, PATH_MAX - path_len); - - ret = stat(path, &stat_buf); - if(ret == -1) { - perror(path); - continue; - } - - g_debug("Tracefile file or directory : %s\n", path); - - if(S_ISDIR(stat_buf.st_mode)) { - - g_debug("Entering subdirectory...\n"); - ret = open_tracefiles(path, tracefiles); - if(ret < 0) continue; - } else if(S_ISREG(stat_buf.st_mode)) { - g_debug("Opening file.\n"); - - GQuark name; - guint num; - GArray *group; - LttTracefile *tf; - guint len; - - if(get_tracefile_name_number(path, &name, &num)) - continue; /* invalid name */ - - group = g_datalist_get_data(tracefiles, name); - if(group == NULL) { - /* Elements are automatically cleared when the array is allocated. - * It makes the cpu_online variable set to 0 : cpu offline, by default. - */ - group = g_array_sized_new (FALSE, TRUE, sizeof(LttTracefile), 10); - g_datalist_set_data_full(tracefiles, name, - group, ltt_tracefile_group_destroy); - } - /* Add the per cpu tracefile to the named group */ - unsigned int old_len = group->len; - if(num+1 > old_len) - group = g_array_set_size(group, num+1); - tf = &g_array_index (group, LttTracefile, num); - - if(ltt_tracefile_open(trace, path, tf)) { - g_info("Error opening tracefile %s", path); - g_array_set_size(group, old_len); - - if(!ltt_tracefile_group_has_cpu_online(group)) - g_datalist_remove_data(tracefiles, name); - - continue; /* error opening the tracefile : bad magic number ? */ - } - tf->cpu_online = 1; - tf->cpu_num = num; - } - } - - closedir(dir); - - return 0; -} - -/* ltt_get_facility_description - * - * Opens the trace corresponding to the requested facility (identified by fac_id - * and checksum). - * - * The name searched is : %trace root%/eventdefs/facname_checksum.xml - * - * Returns 0 on success, or 1 on failure. - */ - -static int ltt_get_facility_description(LttFacility *f, - LttTrace *t) -{ - char desc_file_name[PATH_MAX]; - char *text; - guint textlen; - gint err; - int i, j; - - text = g_quark_to_string(t->pathname); - textlen = strlen(text); - - if(textlen >= PATH_MAX) goto name_error; - strcpy(desc_file_name, text); - - text = "/eventdefs/"; - textlen+=strlen(text); - if(textlen >= PATH_MAX) goto name_error; - strcat(desc_file_name, text); - - text = g_quark_to_string(f->name); - textlen+=strlen(text); - if(textlen >= PATH_MAX) goto name_error; - strcat(desc_file_name, text); - - text = "_"; - textlen+=strlen(text); - if(textlen >= PATH_MAX) goto name_error; - strcat(desc_file_name, text); - - err = snprintf(desc_file_name+textlen, PATH_MAX-textlen-1, - "%u", f->checksum); - if(err) goto name_error; - - textlen=strlen(desc_file_name); - - text = ".xml"; - textlen+=strlen(text); - if(textlen >= PATH_MAX) goto name_error; - strcat(desc_file_name, text); - - err = ltt_facility_open(f, t, desc_file_name); - if(err) goto facility_error; - - for(i=0;ifacilities_by_num->len;i++){ - f = &g_array_index(t->facilities_by_num, LttFacility, i); - if(f->exists) { - for(j=0; jevents->len; j++){ - et = &g_array_index(f->events, LttEventType, j); - setFieldsOffset(NULL, et, NULL); - } - } - } - - - return 0; - -facility_error: -name_error: - return 1; -} - -static void ltt_tracefile_ids_destroy(gpointer data) -{ - GArray *fac_ids = (GArray *)data; - int i; - LttFacility *fac; - - for(i=0; ilen; i++) { - fac = &g_array_index (fac_ids, LttFacility, i); - ltt_facility_close(fac); - } - - g_array_free(array, TRUE); -} - - -/* Presumes the tracefile is already seeked at the beginning. It makes sense, - * because it must be done just after the opening */ -static int ltt_process_facility_tracefile(LttTracefile *tf) -{ - int err; - LttFacility *fac; - GArray *fac_ids; - - while(1) { - err = ltt_tracefile_read_seek(tf); - if(err == EPERM) goto seek_error;; - else if(err == ERANGE) break; /* End of tracefile */ - - err = ltt_tracefile_read_update_event(tf); - if(err) goto update_error; - - /* We are on a facility load/or facility unload/ or heartbeat event */ - /* The rules are : - * * facility 0 is hardcoded : this is the core facility. It will be shown - * in the facility array though, and is shown as "loaded builtin" in the - * trace. - * It contains event : - * 0 : facility load - * 1 : facility unload - * 2 : state dump facility load - * Facility 1 : (heartbeat) - * 0 : heartbeat - */ - if(tf->event.facility_id > 1) { /* Should only contain core and heartbeat - facilities */ - g_warning("Error in processing facility file %s, " - "should not contain facility id %u.", g_quark_to_string(tf->name), - tf->event.facility_id); - err = EPERM; - goto fac_id_error; - } else if(tf->event.facility_id == 0) { - - // FIXME align - switch((enum ltt_core_events)tf->event.event_id) { - case LTT_EVENT_FACILITY_LOAD: - struct LttFacilityLoad *fac_load_data = - (struct LttFacilityLoad *)tf->event.data; - char *fac_name = - (char*)(tf->event.data + sizeof(struct LttFacilityLoad)); - fac = &g_array_index (tf->facilities_by_num, LttTracefile, - tf->event.); - g_assert(fac->exists == 0); - fac->name = g_quark_from_string(fac_name); - fac->checksum = ltt_get_uint32(LTT_GET_BO(tf), - fac_load_data->checksum); - fac->id = ltt_get_uint8(LTT_GET_BO(tf), fac_load_data->id); - fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf), - fac_load_data->pointer_size); - fac->size_t_size = ltt_get_uin32(LTT_GET_BO(tf), - fac_load_data->size_t_size); - fac->alignment = ltt_get_uint32(LTT_GET_BO(tf), - fac_load_data->alignment); - - if(ltt_get_facility_description(fac, tf->trace)) - goto facility_error; - - fac->trace = tf->trace; - fac->exists = 1; - - fac_ids = g_datalist_get_data(tf->facilities_by_name, fac->name); - if(fac_ids == NULL) { - fac_ids = g_array_sized_new (FALSE, TRUE, sizeof(guint), 1); - g_datalist_set_data_full(tf->facilities_by_name, fac->name, - fac_ids, ltt_fac_ids_destroy); - } - g_array_append_val(fac_ids, fac->id); - - break; - case LTT_EVENT_FACILITY_UNLOAD: - /* We don't care about unload : facilities ID are valid for the whole - * trace. They simply won't be used after the unload. */ - break; - case LTT_EVENT_STATE_DUMP_FACILITY_LOAD: - struct LttFacilityLoad *fac_load_data = - (struct LttFacilityLoad *)tf->event.data; - char *fac_name = - (char*)(tf->event.data + sizeof(struct LttFacilityLoad)); - fac = &g_array_index (tf->facilities_by_num, LttTracefile, - tf->event.); - g_assert(fac->exists == 0); - fac->name = g_quark_from_string(fac_name); - fac->checksum = ltt_get_uint32(LTT_GET_BO(tf), - fac_load_data->checksum); - fac->id = ltt_get_uint8(LTT_GET_BO(tf), fac_load_data->id); - fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf), - fac_load_data->pointer_size); - fac->size_t_size = ltt_get_uin32(LTT_GET_BO(tf), - fac_load_data->size_t_size); - fac->alignment = ltt_get_uint32(LTT_GET_BO(tf), - fac_load_data->alignment); - fac->events; - fac->named_types; - fac->named_types_number; - fac->exists = 1; - - fac_ids = g_datalist_get_data(tf->facilities_by_name, fac->name); - if(fac_ids == NULL) { - fac_ids = g_array_sized_new (FALSE, TRUE, sizeof(guint), 1); - g_datalist_set_data_full(tf->facilities_by_name, fac->name, - fac_ids, ltt_fac_ids_destroy); - } - g_array_append_val(fac_ids, fac->id); - - break; - default: - g_warning("Error in processing facility file %s, " - "unknown event id %hhu in core facility.", - g_quark_to_string(tf->name), - tf->event.event_id); - err = EPERM; - goto event_id_error; - } - } else if(tf->event.facility_id == 1) { - - switch((enum ltt_heartbeat_events)tf->event.event_id) { - case LTT_EVENT_HEARTBEAT: - break; - default: - g_warning("Error in processing facility file %s, " - "unknown event id %hhu in heartbeat facility.", - g_quark_to_string(tf->name), - tf->event.event_id); - err = EPERM; - goto event_id_error; - } - } - } - return 0; - - /* Error handling */ -facility_error: -event_id_error: -fac_id_error: -update_error: -seek_error: - return err; -} - - -LttTrace *ltt_trace_open(const gchar *pathname) -{ - gchar abs_path[PATH_MAX]; - LttTrace * t; - LttTracefile *tf; - GArray *group; - int i; - - LttTrace * t = g_new(LttTrace, 1); - if(!t) goto alloc_error; - - get_absolute_pathname(pathname, abs_path); - t->pathname = g_quark_from_string(abs_path); - - /* Open all the tracefiles */ - g_datalist_init(t->tracefiles); - if(open_tracefiles(t, abs_path, t->tracefiles)) - goto open_error; - - /* Prepare the facilities containers : array and mapping */ - /* Array is zeroed : the "exists" field is set to false by default */ - t->facilities_by_num = g_array_sized_new (FALSE, - TRUE, sizeof(LttFacility), - NUM_FACILITIES); - t->facilities_by_num = g_array_set_size(t->facilities_by_num, NUM_FACILITIES); - - g_datalist_init(t->tracefiles_by_name); - - /* Parse each trace control/facilitiesN files : get runtime fac. info */ - group = g_datalist_get_data(t->tracefiles, LTT_TRACEFILE_NAME_FACILITIES); - if(group == NULL) { - g_error("Trace %s has no facility tracefile", abs_path); - goto facilities_error; - } - - for(i=0; ilen; i++) { - tf = &g_array_index (group, LttTracefile, i); - if(ltt_process_facility_tracefile(tf)) - goto facilities_error; - } - - - - return t; - - /* Error handling */ -facilities_error: - g_datalist_free(t->tracefiles_by_name); - g_array_free(t->facilities_by_num, TRUE); -open_error: - g_datalist_clear(t->tracefiles); - g_free(t); -alloc_error: - return NULL; - -} - -GQuark ltt_trace_name(LttTrace *t) -{ - return t->pathname; -} - - -/****************************************************************************** - * When we copy a trace, we want all the opening actions to happen again : - * the trace will be reopened and totally independant from the original. - * That's why we call ltt_trace_open. - *****************************************************************************/ -LttTrace *ltt_trace_copy(LttTrace *self) -{ - return ltt_trace_open(self->pathname); -} - -void ltt_trace_close(LttTrace *t) -{ - g_datalist_free(t->tracefiles_by_name); - g_array_free(t->facilities_by_num, TRUE); - g_datalist_clear(t->tracefiles); - g_free(t); -} - - -/***************************************************************************** - *Get the system description of the trace - ****************************************************************************/ - -LttFacility *ltt_trace_facility_by_id(LttTrace *t, guint8 id) -{ - g_assert(index < t->facilities_by_num->len); - return &g_array_index(t->facilities_by_num, LttFacility, id); -} - -/* ltt_trace_facility_get_by_name - * - * Returns the GArray of facility indexes. All the fac_ids that matches the - * requested facility name. - * - * If name is not found, returns NULL. - */ -GArray *ltt_trace_facility_get_by_name(LttTrace *t, GQuark name) -{ - return g_datalist_id_get_data(t->facilities_by_name, name); -} - -/***************************************************************************** - * Functions to discover all the event types in the trace - ****************************************************************************/ - -#if 0 -unsigned ltt_trace_eventtype_number(LttTrace *t) -{ - unsigned int i; - unsigned count = 0; - unsigned int num = t->facility_number; - LttFacility * f; - - for(i=0;ifacilities, i); - count += f->event_number; - } - return count; -} -#endif //0 - -#if 0 -//use an iteration on all the trace facilities, and inside iteration on all the -//event types in each facilities instead. -LttEventType *ltt_trace_eventtype_get(LttTrace *t, unsigned evId) -{ - LttEventType *event_type; - - LttFacility * f; - f = ltt_trace_facility_by_id(t,evId); - - if(unlikely(!f)) event_type = NULL; - else event_type = f->events[evId - f->base_id]; - - return event_type; -} -#endif //0 - -#if 0 -/***************************************************************************** - * ltt_trace_find_tracefile - * - * Find a tracefile by name and index in the group. - * - * Returns a pointer to the tracefiles, else NULL. - ****************************************************************************/ - -LttTracefile *ltt_trace_find_tracefile(LttTrace *t, const gchar *name) -{ -} -#endif //0 - -/***************************************************************************** - * Get the start time and end time of the trace - ****************************************************************************/ - -static void ltt_tracefile_time_span_get(LttTracefile *tf, - LttTime *start, LttTime *end) -{ - struct ltt_block_start_header * header; - int err; - - err = map_block(tf, 0); - if(unlikely(err)) { - g_error("Can not map block"); - *start = { 0xFFFFFFFF, 0xFFFFFFFF }; - } else - *start = tf->buffer.begin.timestamp; - - err = map_block(tf, tf->num_blocks - 1); /* Last block */ - if(unlikely(err)) { - g_error("Can not map block"); - *end = { 0, 0 }; - } else - *end = tf->buffer.end.timestamp; -} - -struct tracefile_time_span_get_args { - LttTrace *t; - LttTime *start; - LttTime *end; -}; - -static void group_time_span_get(GQuark name, gpointer data, gpointer user_data) -{ - struct tracefile_time_span_get_args *args = - (struct tracefile_time_span_get_args*)user_data; - - GArray *group = (GArray *)data; - int i; - LttTracefile *tf; - LttTime tmp_start; - LttTime tmp_end; - - for(i=0; ilen; i++) { - tf = &g_array_index (group, LttTracefile, i); - if(tf->cpu_online) { - ltt_tracefile_time_span_get(tf, &tmp_start, &tmp_end); - if(ltt_time_compare(*args->start, tmp_start)>0) *args->start = tmp_start; - if(ltt_time_compare(*args->end, tmp_end)<0) *args->end = tmp_end; - } - } -} - -void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end) -{ - LttTime min_start = { 0xFFFFFFFF, 0xFFFFFFFF }; - LttTime max_end = { 0, 0 }; - struct tracefile_time_span_get_args args = { t, &min_start, &max_end }; - - g_datalist_foreach(t->tracefiles, &group_time_span_get, &args); - - if(start != NULL) *start = min_start; - if(end != NULL) *end = max_end; - -} - - -/***************************************************************************** - *Get the name of a tracefile - ****************************************************************************/ - -GQuark ltt_tracefile_name(LttTracefile *tf) -{ - return tf->name; -} - -/***************************************************************************** - * Get the number of blocks in the tracefile - ****************************************************************************/ - -guint ltt_tracefile_block_number(LttTracefile *tf) -{ - return tf->block_number; -} - - -/* Seek to the first event in a tracefile that has a time equal or greater than - * the time passed in parameter. - * - * If the time parameter is outside the tracefile time span, seek to the first - * or the last event of the tracefile. - * - * If the time parameter is before the first event, we have to seek specially to - * there. - * - * If the time is after the end of the trace, get the last event. - * - * Do a binary search to find the right block, then a sequential search in the - * block to find the event. - * - * In the special case where the time requested fits inside a block that has no - * event corresponding to the requested time, the first event of the next block - * will be seeked. - * - * IMPORTANT NOTE : // FIXME everywhere... - * - * You MUST NOT do a ltt_tracefile_read right after a ltt_tracefile_seek_time : - * you will jump over an event if you do. - * - * Return value : 0 : no error, the tf->event can be used - * otherwise : this is an error. - * - * */ - -int ltt_tracefile_seek_time(LttTracefile *tf, LttTime time) -{ - int ret = 0; - int err; - unsigned int block_num, high, low; - - /* seek at the beginning of trace */ - err = map_block(tf, 0); /* First block */ - if(unlikely(err)) { - g_error("Can not map block"); - goto fail; - } - - /* If the time is lower or equal the beginning of the trace, - * go to the first event. */ - if(ltt_time_compare(time, tf->buffer.start.timestamp) <= 0) { - ret = ltt_tracefile_read(tf) - goto found; /* There is either no event in the trace or the event points - to the first event in the trace */ - } - - err = map_block(tf, tf->num_blocks - 1); /* Last block */ - if(unlikely(err)) { - g_error("Can not map block"); - goto fail; - } - - /* If the time is after the end of the trace, get the last event. */ - if(ltt_time_compare(time, tf->buffer.end.timestamp) >= 0) { - /* While the ltt_tracefile_read doesn't return ERANGE or EPERM, - * continue reading. - */ - while(1) { - ret = ltt_tracefile_read(tf); - if(ret == ERANGE) goto found; /* ERANGE or EPERM */ - else if(ret) goto fail; - } - } - - /* Binary search the block */ - high = tf->num_blocks - 1; - low = 0; - - while(1) { - block_num = ((high-low) / 2) + low; - - err = map_block(tf, block_num); - if(unlikely(err)) { - g_error("Can not map block"); - goto fail; - } - if(high == low) { - /* We cannot divide anymore : this is what would happen if the time - * requested was exactly between two consecutive buffers'end and start - * timestamps. This is also what would happend if we didn't deal with out - * of span cases prior in this function. */ - /* The event is right in the buffer! - * (or in the next buffer first event) */ - while(1) { - ret = ltt_tracefile_read(tf); - if(ret == ERANGE) goto found; /* ERANGE or EPERM */ - else if(ret) goto fail; - - if(ltt_time_compare(time, tf->event.event_time) >= 0) - break; - } - - } if(ltt_time_compare(time, tf->buffer.start.timestamp) < 0) { - /* go to lower part */ - high = block_num; - } else if(ltt_time_compare(time, tf->buffer.end.timestamp) > 0) { - /* go to higher part */ - low = block_num; - } else {/* The event is right in the buffer! - (or in the next buffer first event) */ - while(1) { - ltt_tracefile_read(tf); - if(ret == ERANGE) goto found; /* ERANGE or EPERM */ - else if(ret) goto fail; - - if(ltt_time_compare(time, tf->event.event_time) >= 0) - break; - } - goto found; - } - } - -found: - return 0; - - /* Error handling */ -fail: - g_error("ltt_tracefile_seek_time failed on tracefile %s", - g_quark_to_string(tf->name)); - return EPERM; -} - - -int ltt_tracefile_seek_position(LttTracefile *tf, const LttEventPosition *ep) { - - int err; - - if(ep->tracefile != tf) { - goto fail; - } - - err = map_block(tf, ep->block); - if(unlikely(err)) { - g_error("Can not map block"); - goto fail; - } - - tf->event.offset = ep->offset; - - err = ltt_tracefile_read_update_event(tf); - if(err) goto fail; - err = ltt_tracefile_read_op(tf); - if(err) goto fail; - - return; - -fail: - g_error("ltt_tracefile_seek_time failed on tracefile %s", - g_quark_to_string(tf->name)); -} - -/* Calculate the real event time based on the buffer boundaries */ -LttTime ltt_interpolate_time(LttTracefile *tf, LttEvent *event) -{ - LttTime time; - - g_assert(t->trace->has_tsc); - - time = ltt_time_from_uint64( - (guint64)tf->buffer.tsc*tf->buffer.nsecs_per_cycle); - time = ltt_time_add(tf->buffer.begin.timestamp, time); - - return time; -} - -/***************************************************************************** - *Function name - * ltt_tracefile_read : Read the next event in the tracefile - *Input params - * t : tracefile - *Return value - * - * Returns 0 if an event can be used in tf->event. - * Returns ERANGE on end of trace. The event in tf->event still can be used. - * Returns EPERM on error. - * - * This function does make the tracefile event structure point to the event - * currently pointed to by the tf->event. - * - * Note : you must call a ltt_tracefile_seek to the beginning of the trace to - * reinitialize it after an error if you want results to be coherent. - * It would be the case if a end of trace last buffer has no event : the end - * of trace wouldn't be returned, but an error. - * We make the assumption there is at least one event per buffer. - ****************************************************************************/ - -int ltt_tracefile_read(LttTracefile *tf) -{ - int err; - - err = ltt_tracefile_read_seek(tf); - if(err) return err; - err = ltt_tracefile_read_update_event(tf); - if(err) return err; - err = ltt_tracefile_read_op(tf); - if(err) return err; - - return 0; -} - -int ltt_tracefile_read_seek(LttTracefile *tf) -{ - int err; - - /* Get next buffer until we finally have an event, or end of trace */ - while(1) { - err = ltt_seek_next_event(tf); - if(unlikely(err == ENOPROTOOPT)) { - return EPERM; - } - - /* Are we at the end of the buffer ? */ - if(err == ERANGE) { - if(unlikely(tf->buffer.index == tf->num_blocks-1)){ /* end of trace ? */ - return ERANGE; - } else { - /* get next block */ - err = map_block(tf, tf->buffer.index + 1); - if(unlikely(err)) { - g_error("Can not map block"); - return EPERM; - } - } - } else break; /* We found an event ! */ - } - - return 0; -} - - -/* do specific operation on events */ -int ltt_tracefile_read_op(LttTracefile *tf) -{ - int err; - LttFacility *f; - void * pos; - LttEvent *event; - - event = &tf->event; - - /* do event specific operation */ - - /* do something if its an heartbeat event : increment the heartbeat count */ - if(event->facility_id == LTT_FACILITY_CORE) - if(event->event_id == LTT_EVENT_HEARTBEAT) - t->cur_heart_beat_number++; - - return 0; -} - - -/* same as ltt_tracefile_read, but does not seek to the next event nor call - * event specific operation. */ -int ltt_tracefile_read_update_event(LttTracefile *tf) -{ - int err; - LttFacility *f; - void * pos; - LttEvent *event; - - event = &tf->event; - pos = event->offset; - - /* Read event header */ - - //TODO align - - if(tf->trace->has_tsc) { - event->time.timestamp = ltt_get_uint32(LTT_GET_BO(t), - pos); - /* 32 bits -> 64 bits tsc */ - /* note : still works for seek and non seek cases. */ - if(event->time.timestamp < (0xFFFFFFFFULL&tf->buffer.tsc)) { - tf->buffer.tsc = ((tf->buffer.tsc&0xFFFFFFFF00000000ULL) - + 0x100000000ULL) - | (guint64)event->time.timestamp; - event->tsc = tf->buffer.tsc; - } else { - /* no overflow */ - tf->buffer.tsc = (tf->buffer.tsc&0xFFFFFFFF00000000ULL) - | (guint64)event->time.timestamp; - event->tsc = tf->buffer.tsc; - } - - event->event_time = ltt_interpolate_time(tf, event); - - pos += sizeof(uint32); - } else { - event->time.delta = ltt_get_uint32(LTT_GET_BO(tf), - pos); - tf->buffer.tsc = 0; - event->tsc = tf->buffer.tsc; - - event->event_time = ltt_time_add(tf->buffer.begin.timestamp, - event->time_delta); - pos += sizeof(uint32); - } - - event->facility_id = ltt_get_uint8(LTT_GET_BO(tf), - tf->cur_event_pos); - pos += sizeof(uint8); - - event->event_id = ltt_get_uint8(LTT_GET_BO(tf), - tf->cur_event_pos); - pos += sizeof(uint8); - - event->data = tf->cur_event_pos + EVENT_HEADER_SIZE; - - event->data = pos; - - return 0; -} - - -/**************************************************************************** - *Function name - * map_block : map a block from the file - *Input Params - * lttdes : ltt trace file - * whichBlock : the block which will be read - *return value - * 0 : success - * EINVAL : lseek fail - * EIO : can not read from the file - ****************************************************************************/ - -static int map_block(LttTracefile * tf, int block_num) -{ - struct ltt_block_start_header *header; - - g_assert(block_num < tf->num_blocks); - - if(tf->buffer.head != NULL) - munmap(tf->buffer.head, tf->buf_size); - - /* Multiple of pages aligned head */ - tf->buffer.head = mmap(0, tf->block_size, PROT_READ, tf->fd, - (off_t)tf->block_size * (off_t)block_num); - - if(tf->buffer.head == NULL) { - perror("Error in allocating memory for buffer of tracefile %s\n", fileName); - goto map_error; - } - g_assert(tf->buffer.head & (8-1) == 0); // make sure it's aligned. - - - tf->buffer.index = block_num; - - header = (struct ltt_block_start_header*)tf->buffer.head; - - tf->buffer.begin.timestamp = ltt_get_uint64(LTT_GET_BO(tf), - header->begin.timestamp) - * NSEC_PER_USEC; - tf->buffer.begin.cycle_count = ltt_get_uint64(LTT_GET_BO(tf), - header->begin.cycle_count); - tf->buffer.end.timestamp = ltt_get_uint64(LTT_GET_BO(tf), - header->end.timestamp) - * NSEC_PER_USEC; - tf->buffer.end.cycle_count = ltt_get_uint64(LTT_GET_BO(tf), - header->end.cycle_count); - tf->buffer.lost_size = ltt_get_uint32(LTT_GET_BO(tf), - header->lost_size); - - tf->buffer.tsc = tf->buffer.begin.cycle_count; - tf->event.tsc = tf->buffer.tsc; - - /* FIXME - * eventually support variable buffer size : will need a partial pre-read of - * the headers to create an index when we open the trace... eventually. */ - g_assert(tf->block_size == ltt_get_uint32(header->buf_size)); - - /* Now that the buffer is mapped, calculate the time interpolation for the - * block. */ - - tf->buffer.nsecs_per_cycle = calc_nsecs_per_cycle(&tf->buffer); - - /* Make the current event point to the beginning of the buffer : - * it means that the event read must get the first event. */ - tf->event.tracefile = tf; - tf->event.block = block_num; - tf->event.offset = tf->buffer.head; - - return 0; - -map_error: - return -errno; - -} - -ssize_t ltt_get_event_size(LttTracefile *tf) -{ - ssize_t size = 0; - - /* Specific handling of core events : necessary to read the facility control - * tracefile. */ - if(unlikely(tf->event.facility_id == LTT_FACILITY_CORE)) { - switch((enum ltt_core_events)tf->event.event_id) { - case LTT_EVENT_FACILITY_LOAD: - size = sizeof(struct LttFacilityLoad); - break; - case LTT_EVENT_FACILITY_UNLOAD: - size = sizeof(struct LttFacilityUnload); - break; - case LTT_EVENT_STATE_DUMP_FACILITY_LOAD: - size = sizeof(struct LttStateDumpFacilityLoad); - break; - case LTT_EVENT_HEARTBEAT: - size = sizeof(TimeHeartbeat); - break; - default: - g_warning("Error in getting event size : tracefile %s, " - "unknown event id %hhu in core facility.", - g_quark_to_string(tf->name), - tf->event.event_id); - goto event_id_error; - - } - - } else { - LttFacility *f = ltt_trace_get_facility_by_num(tf->trace, - tf->event.facility_id); - LttEventType *event_type = - ltt_facility_eventtype_get(f, tf->event.event_id); - size = get_fields_offsets(tf, event_type, tf->event.data); - } - - return size; - -event_id_error: - return -1; -} - - -/* Take the tf current event offset and use the event facility id and event id - * to figure out where is the next event offset. - * - * This is an internal function not aiming at being used elsewhere : it will - * not jump over the current block limits. Please consider using - * ltt_tracefile_read to do this. - * - * Returns 0 on success - * ERANGE if we are at the end of the buffer. - * ENOPROTOOPT if an error occured when getting the current event size. - */ -static int ltt_seek_next_event(LttTracefile *tf) -{ - int ret = 0; - void *pos; - ssize_t event_size; - - /* seek over the buffer header if we are at the buffer start */ - if(tf->event.offset == tf->buffer.head) { - tf->event.offset += sizeof(struct ltt_block_start_header); - goto found; - } - - - if(tf->event.offset == tf->buffer.head + tf->buffer.lost_size) { - ret = ERANGE; - goto found; - } - - pos = tf->event.data; - - event_size = ltt_get_event_size(tf); - if(event_size < 0) goto error; - - pos += (size_t)event_size; - - tf->event.offset = pos; - -found: - return ret; - -error: - g_error("Error in ltt_seek_next_event for tracefile %s", - g_quark_to_string(tf->name)); - return ENOPROTOOPT; -} - - -/***************************************************************************** - *Function name - * calc_nsecs_per_cycle : calculate nsecs per cycle for current block - *Input Params - * t : tracefile - ****************************************************************************/ - -static double calc_nsecs_per_cycle(LttTracefile * t) -{ - LttTime lBufTotalTime; /* Total time for this buffer */ - double lBufTotalNSec; /* Total time for this buffer in nsecs */ - LttCycleCount lBufTotalCycle;/* Total cycles for this buffer */ - - /* Calculate the total time for this buffer */ - lBufTotalTime = ltt_time_sub( - ltt_get_time(t->buffer.end.timestamp), - ltt_get_time(t->buffer.begin.timestamp)); - - /* Calculate the total cycles for this bufffer */ - lBufTotalCycle = t->buffer.end.cycle_count; - lBufTotalCycle -= t->buffer.start.cycle_count; - - /* Convert the total time to double */ - lBufTotalNSec = ltt_time_to_double(lBufTotalTime); - - return lBufTotalNSec / (double)lBufTotalCycle; - -} -#if 0 -void setFieldsOffset(LttTracefile *tf, LttEventType *evT,void *evD) -{ - LttField * rootFld = evT->root_field; - // rootFld->base_address = evD; - - if(likely(rootFld)) - rootFld->field_size = getFieldtypeSize(tf, evT->facility, - evT, 0,0,rootFld, evD); -} -#endif //0 - -/***************************************************************************** - *Function name - * set_fields_offsets : set the precomputable offset of the fields - *Input params - * tracefile : opened trace file - * event_type : the event type - ****************************************************************************/ - -void set_fields_offsets(LttTracefile *tf, LttEventType *event_type) -{ - LttField *field = event_type->root_field; - - if(likely(field)) - preset_field_type_size(tf, event_type->facility, event_type, 0, 0, - FIELD_FIXED, FIELD_FIXED, - field); - -} - - -/***************************************************************************** - *Function name - * preset_field_type_size : set the fixed sizes of the field type - *Input params - * tf : tracefile - * event_type : event type - * offset_root : offset from the root - * offset_parent : offset from the parent - * fixed_root : Do we know a fixed offset to the root ? - * fixed_parent : Do we know a fixed offset to the parent ? - * field : field - ****************************************************************************/ -void preset_field_type_size(LttTracefile *tf, LttEventType *event_type, - off_t offset_root, off_t offset_parent, - enum field_status *fixed_root, enum field_status *fixed_parent, - LttField *field) -{ - guint i; - LttType *type; - - g_assert(field->fixed_root == FIELD_UNKNOWN); - g_assert(field->fixed_parent == FIELD_UNKNOWN); - g_assert(field->fixed_size == FIELD_UNKNOWN); - - type = field->field_type; - - field->fixed_root = *fixed_root; - if(field->fixed_root == FIELD_FIXED) - field->offset_root = offset_root; - else - field->offset_root = 0; - - field->fixed_parent = *fixed_parent; - if(field->fixed_parent == FIELD_FIXED) - field->offset_parent = offset_parent; - else - field->offset_parent = 0; - - - switch(type->type_class) { - case LTT_INT: - case LTT_UINT: - case LTT_FLOAT: - case LTT_ENUM: - field->field_size = (off_t) ltt_type_size(LTT_GET_BO(tf), - event_type->facility, type); - field->fixed_size = FIELD_FIXED; - break; - case LTT_POINTER: - field->field_size = (off_t)event_type->facility->pointer_size; - field->fixed_size = FIELD_FIXED; - break; - case LTT_LONG: - case LTT_ULONG: - field->field_size = (off_t)event_type->facility->pointer_size; - field->fixed_size = FIELD_FIXED; - break; - case LTT_SIZE_T: - case LTT_SSIZE_T: - case LTT_OFF_T: - field->field_size = (off_t)event_type->facility->size_t_size; - field->fixed_size = FIELD_FIXED; - break; - case LTT_SEQUENCE: - preset_field_type_size(tf, event_type->facility, event_type, - 0, 0, - FIELD_VARIABLE, FIELD_VARIABLE, - field->child[0]); - field->fixed_size = FIELD_VARIABLE; - field->field_size = 0; - break; - case LTT_STRING: - field->fixed_size = FIELD_VARIABLE; - field->field_size = 0; - break; - case LTT_ARRAY: - preset_field_type_size(tf, event_type->facility, event_type, - 0, 0, - FIELD_VARIABLE, FIELD_VARIABLE, - field->child[0]); - field->fixed_size = field->child[0]->fixed_size; - if(field->fixed_size == FIELD_FIXED) - field->field_size = type->element_number * field->child[0]->field_size; - else - field->field_size = 0; - break; - case LTT_STRUCT: - size_t current_root_offset = field->offset_root; - size_t current_offset = 0; - enum field_status current_child_status = FIELD_FIXED; - for(i=0;ielement_number;i++) { - preset_field_type_size(tf, event_type->facility, event_type, - current_root_offset, current_offset, - fixed_root, ¤t_child_status, - field->child[i]); - if(current_child_status == FIELD_FIXED) { - current_root_offset += field->child[i]->field_size; - current_offset += field->child[i]->field_size; - } else { - current_root_offset = 0; - current_offset = 0; - } - } - if(current_child_status != FIELD_FIXED) { - *fixed_parent = current_child_status; - field->field_size = 0; - field->fixed_size = current_child_status; - } else { - field->field_size = current_offset; - field->fixed_size = FIELD_FIXED; - } - break; - case LTT_UNION: - size_t current_root_offset = field->offset_root; - size_t current_offset = 0; - size_t max_size = 0; - enum field_status final_child_status = FIELD_FIXED; - for(i=0;ielement_number;i++) { - enum field_status current_root_child_status = FIELD_FIXED; - enum field_status current_child_status = FIELD_FIXED; - preset_field_type_size(tf, event_type->facility, event_type, - current_root_offset, current_offset, - ¤t_root_child_status, ¤t_child_status, - field->child[i]); - if(current_child_status != FIELD_FIXED) - final_child_status = current_child_status; - else - max_size = max(max_size, field->child[i]->field_size); - } - if(final_child_status != FIELD_FIXED) { - *fixed_root = final_child_status; - *fixed_parent = final_child_status; - field->field_size = 0; - field->fixed_size = current_child_status; - } else { - field->field_size = max_size; - field->fixed_size = FIELD_FIXED; - } - break; - } - -} - - -/***************************************************************************** - *Function name - * get_field_type_size : set the fixed and dynamic sizes of the field type - * from the data read. - *Input params - * tf : tracefile - * event_type : event type - * offset_root : offset from the root - * offset_parent : offset from the parent - * field : field - * data : a pointer to the event data. - *Returns the field type size. - ****************************************************************************/ -size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type, - off_t offset_root, off_t offset_parent, - LttField *field, void *data) -{ - size_t size = 0; - guint i; - LttType *type; - - g_assert(field->fixed_root != FIELD_UNKNOWN); - g_assert(field->fixed_parent != FIELD_UNKNOWN); - g_assert(field->fixed_size != FIELD_UNKNOWN); - - field->offset_root = offset_root; - field->offset_parent = offset_parent; - - type = field->field_type; - - switch(type->type_class) { - case LTT_INT: - case LTT_UINT: - case LTT_FLOAT: - case LTT_ENUM: - case LTT_POINTER: - case LTT_LONG: - case LTT_ULONG: - case LTT_SIZE_T: - case LTT_SSIZE_T: - case LTT_OFF_T: - g_assert(field->fixed_size == FIELD_FIXED); - size = field->field_size; - break; - case LTT_SEQUENCE: - gint seqnum = ltt_get_uint(LTT_GET_BO(tf), - field->sequ_number_size, - data + offset_root); - - if(field->child[0]->fixed_size == FIELD_FIXED) { - size = field->sequ_number_size + - (seqnum * get_field_type_size(tf, event_type->facility, event_type, - offset_root, offset_parent, - field->child[0], data)); - } else { - size += field->sequ_number_size; - for(i=0;ifacility, - event_type, - offset_root, offset_parent, - field->child[0], data); - offset_root += child_size; - offset_parent += child_size; - size += child_size; - } - } - field->field_size = size; - break; - case LTT_STRING: - size = strlen((char*)(data+offset_root)) + 1;// length + \0 - field->field_size = size; - break; - case LTT_ARRAY: - if(field->fixed_size == FIELD_FIXED) - size = field->field_size; - else { - for(i=0;ifacility, - event_type, - offset_root, offset_parent, - field->child[0], data); - offset_root += child_size; - offset_parent += child_size; - size += child_size; - } - field->field_size = size; - } - break; - case LTT_STRUCT: - if(field->fixed_size == FIELD_FIXED) - size = field->field_size; - else { - size_t current_root_offset = offset_root; - size_t current_offset = 0; - size_t child_size = 0; - for(i=0;ielement_number;i++) { - child_size = get_field_type_size(tf, event_type->facility, - event_type, current_root_offset, current_offset, - field->child[i], data); - current_offset += child_size; - current_root_offset += child_size; - - } - size = current_offset; - field->field_size = size; - } - break; - case LTT_UNION: - if(field->fixed_size == FIELD_FIXED) - size = field->field_size; - else { - size_t current_root_offset = field->offset_root; - size_t current_offset = 0; - for(i=0;ielement_number;i++) { - size = get_field_type_size(tf, event_type->facility, event_type, - current_root_offset, current_offset, - field->child[i], data); - size = max(size, field->child[i]->field_size); - } - field->field_size = size; - } - break; - } - - return size; -} - - - -#if 0 -/***************************************************************************** - *Function name - * getFieldtypeSize: get the size of the field type (primitive type) - *Input params - * evT : event type - * offsetRoot : offset from the root - * offsetParent : offset from the parrent - * fld : field - * evD : event data, it may be NULL - *Return value - * int : size of the field - ****************************************************************************/ - -static inline gint getFieldtypeSize(LttTracefile *tf, - LttEventType * evT, gint offsetRoot, - gint offsetParent, LttField * fld, void *evD) -{ - gint size, size1, element_number, i, offset1, offset2; - LttType * type = fld->field_type; - - /* This likely has been tested with gcov : half of them.. */ - if(unlikely(fld->field_fixed == 1)){ - /* tested : none */ - if(unlikely(fld == evT->root_field)) { - size = fld->field_size; - goto end_getFieldtypeSize; - } - } - - /* From gcov profiling : half string, half struct, can we gain something - * from that ? (Mathieu) */ - switch(type->type_class) { - case LTT_ARRAY: - element_number = (int) type->element_number; - if(fld->field_fixed == -1){ - size = getFieldtypeSize(tf, evT, offsetRoot, - 0,fld->child[0], NULL); - if(size == 0){ //has string or sequence - fld->field_fixed = 0; - }else{ - fld->field_fixed = 1; - size *= element_number; - } - }else if(fld->field_fixed == 0){// has string or sequence - size = 0; - for(i=0;ichild[0], evD+size); - } - }else size = fld->field_size; - if(unlikely(!evD)){ - fld->fixed_root = (offsetRoot==-1) ? 0 : 1; - fld->fixed_parent = (offsetParent==-1) ? 0 : 1; - } - - break; - - case LTT_SEQUENCE: - size1 = (int) ltt_type_size(fac, type); - if(fld->field_fixed == -1){ - fld->sequ_number_size = size1; - fld->field_fixed = 0; - size = getFieldtypeSize(evT, offsetRoot, - 0,fld->child[0], NULL); - fld->element_size = size; - }else{//0: sequence - element_number = getIntNumber(tf,size1,evD); - type->element_number = element_number; - if(fld->element_size > 0){ - size = element_number * fld->element_size; - }else{//sequence has string or sequence - size = 0; - for(i=0;ichild[0], evD+size+size1); - } - } - size += size1; - } - if(unlikely(!evD)){ - fld->fixed_root = (offsetRoot==-1) ? 0 : 1; - fld->fixed_parent = (offsetParent==-1) ? 0 : 1; - } - - break; - - case LTT_STRING: - size = 0; - if(fld->field_fixed == -1){ - fld->field_fixed = 0; - }else{//0: string - /* Hope my implementation is faster than strlen (Mathieu) */ - char *ptr=(char*)evD; - size = 1; - /* from gcov : many many strings are empty, make it the common case.*/ - while(unlikely(*ptr != '\0')) { size++; ptr++; } - //size = ptr - (char*)evD + 1; //include end : '\0' - } - fld->fixed_root = (offsetRoot==-1) ? 0 : 1; - fld->fixed_parent = (offsetParent==-1) ? 0 : 1; - - break; - - case LTT_STRUCT: - element_number = (int) type->element_number; - size = 0; - /* tested with gcov */ - if(unlikely(fld->field_fixed == -1)){ - offset1 = offsetRoot; - offset2 = 0; - for(i=0;ichild[i], NULL); - if(likely(size1 > 0 && size >= 0)){ - size += size1; - if(likely(offset1 >= 0)) offset1 += size1; - offset2 += size1; - }else{ - size = -1; - offset1 = -1; - offset2 = -1; - } - } - if(unlikely(size == -1)){ - fld->field_fixed = 0; - size = 0; - }else fld->field_fixed = 1; - }else if(likely(fld->field_fixed == 0)){ - offset1 = offsetRoot; - offset2 = 0; - for(i=0;unlikely(ichild[i], evD+offset2); - offset1 += size; - offset2 += size; - } - size = offset2; - }else size = fld->field_size; - fld->fixed_root = (offsetRoot==-1) ? 0 : 1; - fld->fixed_parent = (offsetParent==-1) ? 0 : 1; - break; - - default: - if(unlikely(fld->field_fixed == -1)){ - size = (int) ltt_type_size(LTT_GET_BO(tf), type); - fld->field_fixed = 1; - }else size = fld->field_size; - if(unlikely(!evD)){ - fld->fixed_root = (offsetRoot==-1) ? 0 : 1; - fld->fixed_parent = (offsetParent==-1) ? 0 : 1; - } - break; - } - - fld->offset_root = offsetRoot; - fld->offset_parent = offsetParent; - fld->field_size = size; - -end_getFieldtypeSize: - - return size; -} -#endif //0 - -/***************************************************************************** - *Function name - * get_int : get an integer number - *Input params - * reverse_byte_order: must we reverse the byte order ? - * size : the size of the integer - * ptr : the data pointer - *Return value - * gint64 : a 64 bits integer - ****************************************************************************/ - -gint64 get_int(gboolean reverse_byte_order, gint size, void *data) -{ - gint64 val; - - switch(size) { - case 1: val = *((gint8*)data); break; - case 2: val = ltt_get_int16(reverse_byte_order, data); break; - case 4: val = ltt_get_int32(reverse_byte_order, data); break; - case 8: val = ltt_get_int64(reverse_byte_order, data); break; - default: val = ltt_get_int64(reverse_byte_order, data); - g_critical("get_int : integer size %d unknown", size); - break; - } - - return val; -} - -/***************************************************************************** - *Function name - * get_uint : get an unsigned integer number - *Input params - * reverse_byte_order: must we reverse the byte order ? - * size : the size of the integer - * ptr : the data pointer - *Return value - * guint64 : a 64 bits unsigned integer - ****************************************************************************/ - -guint64 get_uint(gboolean reverse_byte_order, gint size, void *data) -{ - guint64 val; - - switch(size) { - case 1: val = *((gint8*)data); break; - case 2: val = ltt_get_uint16(reverse_byte_order, data); break; - case 4: val = ltt_get_uint32(reverse_byte_order, data); break; - case 8: val = ltt_get_uint64(reverse_byte_order, data); break; - default: val = ltt_get_uint64(reverse_byte_order, data); - g_critical("get_uint : unsigned integer size %d unknown", - size); - break; - } - - return val; -} - - -/* get the node name of the system */ - -char * ltt_trace_system_description_node_name (LttSystemDescription * s) -{ - return s->node_name; -} - - -/* get the domain name of the system */ - -char * ltt_trace_system_description_domain_name (LttSystemDescription * s) -{ - return s->domain_name; -} - - -/* get the description of the system */ - -char * ltt_trace_system_description_description (LttSystemDescription * s) -{ - return s->description; -} - - -/* get the start time of the trace */ - -LttTime ltt_trace_system_description_trace_start_time(LttSystemDescription *s) -{ - return s->trace_start; -} - - -LttTracefile *ltt_tracefile_new() -{ - return g_new(LttTracefile, 1); -} - -void ltt_tracefile_destroy(LttTracefile *tf) -{ - g_free(tf); -} - -void ltt_tracefile_copy(LttTracefile *dest, const LttTracefile *src) -{ - *dest = *src; -} - -/* Before library loading... */ - -static void __attribute__((constructor)) init(void) -{ - LTT_FACILITY_NAME_HEARTBEAT = g_quark_from_string("heartbeat"); - LTT_EVENT_NAME_HEARTBEAT = g_quark_from_string("heartbeat"); - - LTT_TRACEFILE_NAME_FACILITIES = g_quark_from_string("control/facilities"); -} - diff --git a/ltt/branches/poly/ltt-newlib/Makefile.am b/ltt/branches/poly/ltt-oldlib/Makefile.am similarity index 100% rename from ltt/branches/poly/ltt-newlib/Makefile.am rename to ltt/branches/poly/ltt-oldlib/Makefile.am diff --git a/ltt/branches/poly/ltt-newlib/compiler.h b/ltt/branches/poly/ltt-oldlib/compiler.h similarity index 100% rename from ltt/branches/poly/ltt-newlib/compiler.h rename to ltt/branches/poly/ltt-oldlib/compiler.h diff --git a/ltt/branches/poly/ltt-newlib/convert/LTTTypes.h b/ltt/branches/poly/ltt-oldlib/convert/LTTTypes.h similarity index 100% rename from ltt/branches/poly/ltt-newlib/convert/LTTTypes.h rename to ltt/branches/poly/ltt-oldlib/convert/LTTTypes.h diff --git a/ltt/branches/poly/ltt-newlib/convert/LinuxEvents.h b/ltt/branches/poly/ltt-oldlib/convert/LinuxEvents.h similarity index 100% rename from ltt/branches/poly/ltt-newlib/convert/LinuxEvents.h rename to ltt/branches/poly/ltt-oldlib/convert/LinuxEvents.h diff --git a/ltt/branches/poly/ltt-newlib/convert/Makefile.am b/ltt/branches/poly/ltt-oldlib/convert/Makefile.am similarity index 100% rename from ltt/branches/poly/ltt-newlib/convert/Makefile.am rename to ltt/branches/poly/ltt-oldlib/convert/Makefile.am diff --git a/ltt/branches/poly/ltt-newlib/convert/README b/ltt/branches/poly/ltt-oldlib/convert/README similarity index 100% rename from ltt/branches/poly/ltt-newlib/convert/README rename to ltt/branches/poly/ltt-oldlib/convert/README diff --git a/ltt/branches/poly/ltt-newlib/convert/convert.c b/ltt/branches/poly/ltt-oldlib/convert/convert.c similarity index 100% rename from ltt/branches/poly/ltt-newlib/convert/convert.c rename to ltt/branches/poly/ltt-oldlib/convert/convert.c diff --git a/ltt/branches/poly/ltt-newlib/convert/core.xml b/ltt/branches/poly/ltt-oldlib/convert/core.xml similarity index 100% rename from ltt/branches/poly/ltt-newlib/convert/core.xml rename to ltt/branches/poly/ltt-oldlib/convert/core.xml diff --git a/ltt/branches/poly/ltt-newlib/convert/sysInfo b/ltt/branches/poly/ltt-oldlib/convert/sysInfo similarity index 100% rename from ltt/branches/poly/ltt-newlib/convert/sysInfo rename to ltt/branches/poly/ltt-oldlib/convert/sysInfo diff --git a/ltt/branches/poly/ltt-newlib/crc32.tab b/ltt/branches/poly/ltt-oldlib/crc32.tab similarity index 100% rename from ltt/branches/poly/ltt-newlib/crc32.tab rename to ltt/branches/poly/ltt-oldlib/crc32.tab diff --git a/ltt/branches/poly/ltt-newlib/event.c b/ltt/branches/poly/ltt-oldlib/event.c similarity index 73% rename from ltt/branches/poly/ltt-newlib/event.c rename to ltt/branches/poly/ltt-oldlib/event.c index fe299b5d..02ecf271 100644 --- a/ltt/branches/poly/ltt-newlib/event.c +++ b/ltt/branches/poly/ltt-oldlib/event.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -47,8 +46,6 @@ void ltt_event_destroy(LttEvent *event) } -#if 0 -/* Use get_field_type_size instead */ /***************************************************************************** *Function name * ltt_event_refresh_fields : refresh fields of an event @@ -175,8 +172,6 @@ int ltt_event_refresh_fields(int offsetRoot,int offsetParent, return size; } -#endif //0 - /***************************************************************************** *Function name @@ -222,7 +217,7 @@ LttEventType *ltt_event_eventtype(LttEvent *e) { LttFacility* facility = ltt_event_facility(e); if(!facility) return NULL; - return &g_array_index(facility->events, LttEventType, e->event_id); + return facility->events[e->event_id - facility->base_id]; } /***************************************************************************** @@ -242,9 +237,17 @@ LttField *ltt_event_field(LttEvent *e) field = event_type->root_field; if(unlikely(!field)) return NULL; - get_field_type_size(e->tracefile, event_type, 0, 0, - field, e->data); - + //check if the field need refresh + if(likely(e->which_block != event_type->latest_block || + e->which_event != event_type->latest_event)){ + + event_type->latest_block = e->which_block; + event_type->latest_event = e->which_event; + + if(unlikely(field->field_fixed != 1)) + ltt_event_refresh_fields(0, 0, field, e->data, + e->tracefile->trace->reverse_byte_order); + } return field; } @@ -273,7 +276,7 @@ LttTime ltt_event_time(LttEvent *e) LttCycleCount ltt_event_cycle_count(LttEvent *e) { - return e->tsc; + return e->event_cycle_count; } /***************************************************************************** @@ -286,10 +289,24 @@ LttCycleCount ltt_event_cycle_count(LttEvent *e) void ltt_event_position(LttEvent *e, LttEventPosition *ep) { - ep->tracefile = e->tracefile; - ep->block = e->block; - ep->offset = e->offset; - ep->tsc = e->tsc; + ep->block_num = e->which_block; + ep->event_num = e->which_event; + ep->event_time = e->event_time; + ep->event_cycle_count = e->event_cycle_count; + ep->heart_beat_number = e->tracefile->cur_heart_beat_number; + ep->old_position = TRUE; + ep->event_offset = e->data - e->tracefile->buffer - EVENT_HEADER_SIZE ; + ep->tf = e->tracefile; + ep->overflow_nsec = e->overflow_nsec; + /* This is a workaround for fast position seek */ + ep->last_event_pos = e->last_event_pos; + ep->prev_block_end_time = e->prev_block_end_time; + ep->prev_event_time = e->prev_event_time; + ep->pre_cycle_count = e->pre_cycle_count; + ep->count = e->count; + ep->last_heartbeat = e->last_heartbeat; + + /* end of workaround */ } LttEventPosition * ltt_event_position_new() @@ -297,6 +314,44 @@ LttEventPosition * ltt_event_position_new() return g_new(LttEventPosition, 1); } +/***************************************************************************** + *Function name + * ltt_event_position_get : get the block number and index of the event + *Input params + * ep : a pointer to event's position structure + * block_number : the block number of the event + * index_in_block : the index of the event within the block + ****************************************************************************/ + +void ltt_event_position_get(LttEventPosition *ep, + unsigned *block_number, unsigned *index_in_block, LttTracefile ** tf) +{ + *block_number = ep->block_num; + *index_in_block = ep->event_num; + *tf = ep->tf; +} + +/***************************************************************************** + *Function name + * ltt_event_position_set : set the block number and index of the event + * It does put the old_position gboolean to FALSE, as it is impossible + * to know the quick position to seek in the tracefile. + *Input params + * ep : a pointer to event's position structure + * block_number : the block number of the event + * index_in_block : the index of the event within the block + ****************************************************************************/ + +void ltt_event_position_set(LttEventPosition *ep, + unsigned block_number, unsigned index_in_block) +{ + if(ep->block_num != block_number || ep->event_num != index_in_block) + ep->old_position = FALSE; + + ep->block_num = block_number; + ep->event_num = index_in_block; + +} /***************************************************************************** * Function name @@ -315,23 +370,58 @@ LttEventPosition * ltt_event_position_new() gint ltt_event_position_compare(const LttEventPosition *ep1, const LttEventPosition *ep2) { + if(ep1->tf != ep2->tf) + g_error("ltt_event_position_compare on different tracefiles makes no sense"); if(ep1 == NULL && ep2 == NULL) return 0; if(ep1 != NULL && ep2 == NULL) return -1; if(ep1 == NULL && ep2 != NULL) return 1; + + if(ep1->block_num < ep2->block_num) + return -1; + if(ep1->block_num > ep2->block_num) + return 1; + if(ep1->event_num < ep2->event_num) + return -1; + if(ep1->event_num > ep2->event_num) + return 1; + return 0; +} - if(ep1->tracefile != ep2->tracefile) - g_error("ltt_event_position_compare on different tracefiles makes no sense"); - - if(ep1->block < ep2->block) +/***************************************************************************** + * Function name + * ltt_event_event_position_compare : compare two positions, one in event, + * other in position opaque structure. + * Input params + * event : a pointer to event structure + * ep : a pointer to event's position structure + * Return + * -1 is event < ep + * 1 if event > ep + * 0 if event == ep + ****************************************************************************/ + +gint ltt_event_event_position_compare(const LttEvent *event, + const LttEventPosition *ep) +{ + if(event == NULL && ep == NULL) + return 0; + if(event != NULL && ep == NULL) + return -1; + if(event == NULL && ep != NULL) + return 1; + + g_assert(event->tracefile == ep->tf); + + if(event->which_block < ep->block_num) return -1; - if(ep1->block > ep2->block) + if(event->which_block > ep->block_num) return 1; - if(ep1->offset < ep2->offset) + if(event->which_event < ep->event_num) return -1; - if(ep1->offset > ep2->offset) + if(event->which_event > ep->event_num) return 1; return 0; } @@ -365,8 +455,23 @@ void ltt_event_position_copy(LttEventPosition *dest, ****************************************************************************/ unsigned ltt_event_cpu_id(LttEvent *e) -{ - return e->tracefile->cpu_num; +{ + gchar * c1, * c2, * c3; + c1 = strrchr(e->tracefile->name,'\\'); + c2 = strrchr(e->tracefile->name,'/'); + if(c1 == NULL && c2 == NULL){ + return (unsigned)atoi(e->tracefile->name); + }else if(c1 == NULL){ + c2++; + return (unsigned)atoi(c2); + }else if(c2 == NULL){ + c1++; + return (unsigned)atoi(c1); + }else{ + c3 = (c1 > c2) ? c1 : c2; + c3++; + return (unsigned)atoi(c3); + } } /***************************************************************************** @@ -395,7 +500,8 @@ void *ltt_event_data(LttEvent *e) *Return value * unsigned : the number of elements for an array/sequence field ****************************************************************************/ -guint64 ltt_event_field_element_number(LttEvent *e, LttField *f) + +unsigned ltt_event_field_element_number(LttEvent *e, LttField *f) { if(f->field_type->type_class != LTT_ARRAY && f->field_type->type_class != LTT_SEQUENCE) @@ -403,8 +509,8 @@ guint64 ltt_event_field_element_number(LttEvent *e, LttField *f) if(f->field_type->type_class == LTT_ARRAY) return f->field_type->element_number; - return get_unsigned(LTT_GET_BO(e->tracefile), f->sequ_number_size, - e + f->offset_root); + return (unsigned) getIntNumber(e->tracefile->trace->reverse_byte_order, + f->sequ_number_size, e + f->offset_root); } /***************************************************************************** @@ -412,60 +518,50 @@ guint64 ltt_event_field_element_number(LttEvent *e, LttField *f) * ltt_event_field_element_select * : Set the currently selected element for a sequence or * array field - * O(1) if fields are of fixed size, else O(n) if fields are - * of variable size. *Input params * e : an instance of an event type * f : a field of the instance - * i : the ith element (0, ...) + * i : the ith element ****************************************************************************/ + void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i) { unsigned element_number; - LttField *field; + LttField *fld; unsigned int k; - size_t size; - LttEventType *event_type; + int size; + void *evD; if(f->field_type->type_class != LTT_ARRAY && f->field_type->type_class != LTT_SEQUENCE) return ; element_number = ltt_event_field_element_number(e,f); - event_type = ltt_event_eventtype(e); - /* Sanity check for i : 0..n-1 only, and must be lower or equal element_number + /* Sanity check for i : 1..n only, and must be lower or equal element_number */ - if(i >= element_number) return; + if(element_number < i || i == 0) return; - field = f->child[0]; - - if(f->field_type->type_class == LTT_SEQUENCE) - size = f->sequ_number_size; - else - size = 0; + fld = f->child[0]; - if(field->fixed_size == FIELD_FIXED) { - size += field->field_size * i; - - get_field_type_size(e->tracefile, event_type, - f->offset_root+size, size, field, e->data); - - } else { - for(k=0;k<=i;k++){ - size += get_field_type_size(e->tracefile, event_type, - f->offset_root+size, size, field, e->data); - } + evD = e->data + f->offset_root; + size = 0; + for(k=0;koffset_root+size,size, fld, evD+size, + e->tracefile->trace->reverse_byte_order); } - f->current_element = i; + f->current_element = i - 1; } /***************************************************************************** * These functions extract data from an event after architecture specific * conversions ****************************************************************************/ + guint32 ltt_event_get_unsigned(LttEvent *e, LttField *f) { - gboolean reverse_byte_order = LTT_GET_BO(e->tracefile); + //int revFlag = e->tracefile->trace->my_arch_endian == + // e->tracefile->trace->system_description->endian ? 0:1; + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; LttTypeEnum t = f->field_type->type_class; @@ -494,7 +590,9 @@ guint32 ltt_event_get_unsigned(LttEvent *e, LttField *f) gint32 ltt_event_get_int(LttEvent *e, LttField *f) { - gboolean reverse_byte_order = LTT_GET_BO(e->tracefile); + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; + //int revFlag = e->tracefile->trace->my_arch_endian == + // e->tracefile->trace->system_description->endian ? 0:1; g_assert(f->field_type->type_class == LTT_INT); @@ -521,8 +619,9 @@ gint32 ltt_event_get_int(LttEvent *e, LttField *f) guint64 ltt_event_get_long_unsigned(LttEvent *e, LttField *f) { - gboolean reverse_byte_order = LTT_GET_BO(e->tracefile); - + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; + //int revFlag = e->tracefile->trace->my_arch_endian == + // e->tracefile->trace->system_description->endian ? 0:1; LttTypeEnum t = f->field_type->type_class; g_assert(t == LTT_UINT || t == LTT_ENUM); @@ -545,7 +644,7 @@ gint64 ltt_event_get_long_int(LttEvent *e, LttField *f) { //int revFlag = e->tracefile->trace->my_arch_endian == // e->tracefile->trace->system_description->endian ? 0:1; - gboolean reverse_byte_order = LTT_GET_BO(e->tracefile); + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; g_assert( f->field_type->type_class == LTT_INT); @@ -565,7 +664,9 @@ gint64 ltt_event_get_long_int(LttEvent *e, LttField *f) float ltt_event_get_float(LttEvent *e, LttField *f) { - gboolean reverse_byte_order = LTT_GET_BO(e->tracefile); + //int revFlag = e->tracefile->trace->my_arch_endian == + // e->tracefile->trace->system_description->endian ? 0:1; + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; g_assert(f->field_type->type_class == LTT_FLOAT && f->field_size == 4); @@ -580,7 +681,9 @@ float ltt_event_get_float(LttEvent *e, LttField *f) double ltt_event_get_double(LttEvent *e, LttField *f) { - gboolean reverse_byte_order = LTT_GET_BO(e->tracefile); + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; + //int revFlag = e->tracefile->trace->my_arch_endian == + // e->tracefile->trace->system_description->endian ? 0:1; g_assert(f->field_type->type_class == LTT_FLOAT && f->field_size == 8); @@ -597,6 +700,7 @@ double ltt_event_get_double(LttEvent *e, LttField *f) * The string obtained is only valid until the next read from * the same tracefile. ****************************************************************************/ + char *ltt_event_get_string(LttEvent *e, LttField *f) { g_assert(f->field_type->type_class == LTT_STRING); diff --git a/ltt/branches/poly/ltt-newlib/event.h b/ltt/branches/poly/ltt-oldlib/event.h similarity index 98% rename from ltt/branches/poly/ltt-newlib/event.h rename to ltt/branches/poly/ltt-oldlib/event.h index fc50fee9..3f1f8972 100644 --- a/ltt/branches/poly/ltt-newlib/event.h +++ b/ltt/branches/poly/ltt-oldlib/event.h @@ -19,7 +19,6 @@ #ifndef EVENT_H #define EVENT_H -#include #include LttEvent *ltt_event_new(); @@ -97,7 +96,7 @@ void *ltt_event_data(LttEvent *e); instance. This function returns the number of elements for an array or sequence field in an event. */ -guint64 ltt_event_field_element_number(LttEvent *e, LttField *f); +unsigned ltt_event_field_element_number(LttEvent *e, LttField *f); /* Set the currently selected element for a sequence or array field. */ diff --git a/ltt/branches/poly/ltt-newlib/facility.c b/ltt/branches/poly/ltt-oldlib/facility.c similarity index 77% rename from ltt/branches/poly/ltt-newlib/facility.c rename to ltt/branches/poly/ltt-oldlib/facility.c index 9eb5627f..84baac98 100644 --- a/ltt/branches/poly/ltt-newlib/facility.c +++ b/ltt/branches/poly/ltt-oldlib/facility.c @@ -1,6 +1,5 @@ /* This file is part of the Linux Trace Toolkit viewer * Copyright (C) 2003-2004 Xiangxiu Yang - * 2005 Mathieu Desnoyers * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as @@ -68,16 +67,15 @@ void freeLttNamedType(LttType * type); *Input params * t : the trace containing the facilities * pathname : the path name of the facility - * - *returns 0 on success, 1 on error. ****************************************************************************/ -int ltt_facility_open(LttFacility *f, LttTrace * t, gchar * pathname) +void ltt_facility_open(LttTrace * t, gchar * pathname) { gchar *token; parse_file in; gsize length; facility_t * fac; + LttFacility * f; LttChecksum checksum; GError * error = NULL; gchar buffer[BUFFER_SIZE]; @@ -88,11 +86,7 @@ int ltt_facility_open(LttFacility *f, LttTrace * t, gchar * pathname) in.name = pathname; in.fd = g_open(in.name, O_RDONLY, 0); - if(in.fd < 0 ) { - g_warning("cannot open facility description file %s", - in.name); - return 1; - } + if(in.fd < 0 ) in.error(&in,"cannot open input file"); in.channel = g_io_channel_unix_new(in.fd); in.pos = 0; @@ -119,8 +113,13 @@ int ltt_facility_open(LttFacility *f, LttTrace * t, gchar * pathname) g_assert(generateChecksum(fac->name, &checksum, &fac->events) == 0); + f = g_new(LttFacility,1); + f->base_id = 0; generateFacility(f, fac, checksum); + t->facility_number++; + g_ptr_array_add(t->facilities,f); + g_free(fac->name); g_free(fac->description); freeEvents(&fac->events); @@ -131,13 +130,9 @@ int ltt_facility_open(LttFacility *f, LttTrace * t, gchar * pathname) sequence_dispose(&fac->unnamed_types); g_free(fac); } - else { - g_warning("facility token was expected in file %s", in.name); - goto parse_error; - } + else in.error(&in,"facility token was expected"); } - parse_error: g_io_channel_shutdown(in.channel, FALSE, &error); /* No flush */ if(error != NULL) { g_warning("Can not close file: \n%s\n", error->message); @@ -162,51 +157,32 @@ void generateFacility(LttFacility *f, facility_t *fac,LttChecksum checksum) char * facilityName = fac->name; sequence * events = &fac->events; int i; - //LttEventType * evType; - LttEventType * event_type; + LttEventType * evType; LttField * field; LttType * type; - g_assert(f->name == g_quark_from_string(facilityName)); - g_assert(f->checksum == checksum); - - //f->event_number = events->position; + f->name = g_strdup(facilityName); + f->event_number = events->position; + f->checksum = checksum; //initialize inner structures - f->events = g_array_sized_new (FALSE, TRUE, sizeof(LttEventType), - events->position); - //f->events = g_new(LttEventType*,f->event_number); - f->events = g_array_set_size(f->events, events->position); - - g_datalist_init(f->events_by_name); - g_datalist_init(f->named_types); - - //f->named_types_number = fac->named_types.keys.position; - //f->named_types = g_array_sized_new (FALSE, TRUE, sizeof(LttType), - // fac->named_types.keys.position); - //f->named_types = g_new(LttType*, fac->named_types.keys.position); - //f->named_types = g_array_set_size(f->named_types, - // fac->named_types.keys.position); + f->events = g_new(LttEventType*,f->event_number); + f->named_types_number = fac->named_types.keys.position; + f->named_types = g_new(LttType*, fac->named_types.keys.position); + for(i=0;inamed_types.keys.position;i++) f->named_types[i] = NULL; //for each event, construct field tree and type graph for(i=0;iposition;i++){ - event_type = &g_array_index(f->events, LttEventType, i); - //evType = g_new(LttEventType,1); - //f->events[i] = evType; + evType = g_new(LttEventType,1); + f->events[i] = evType; - event_type->name = - g_quark_from_string(((event_t*)(events->array[i]))->name); - - g_datalist_set_data(f->events_by_name, event_type->name, - event_type); - - event_type->description = - g_strdup(((event_t*)(events->array[i]))->description); + evType->name = g_strdup(((event_t*)(events->array[i]))->name); + evType->description=g_strdup(((event_t*)(events->array[i]))->description); field = g_new(LttField, 1); - event_type->root_field = field; - event_type->facility = f; - event_type->index = i; + evType->root_field = field; + evType->facility = f; + evType->index = i; if(((event_t*)(events->array[i]))->type != NULL){ field->field_pos = 0; @@ -243,7 +219,7 @@ void generateFacility(LttFacility *f, facility_t *fac,LttChecksum checksum) * root_field : root field of the event ****************************************************************************/ -void constructTypeAndFields(LttFacility * fac, type_descriptor * td, +void constructTypeAndFields(LttFacility * fac,type_descriptor * td, LttField * fld) { int i, flag; @@ -255,10 +231,10 @@ void constructTypeAndFields(LttFacility * fac, type_descriptor * td, if(td->type == LTT_ENUM){ fld->field_type->element_number = td->labels.position; - fld->field_type->enum_strings = g_new(GQuark,td->labels.position); + fld->field_type->enum_strings = g_new(char*,td->labels.position); for(i=0;ilabels.position;i++){ fld->field_type->enum_strings[i] - = g_quark_from_string(((char*)(td->labels.array[i]))); + = g_strdup(((char*)(td->labels.array[i]))); } }else if(td->type == LTT_ARRAY || td->type == LTT_SEQUENCE){ if(td->type == LTT_ARRAY) @@ -304,8 +280,8 @@ void constructTypeAndFields(LttFacility * fac, type_descriptor * td, fld->child[i]->field_type = fld->field_type->element_type[i]; if(flag){ - fld->child[i]->field_type->element_name - = g_quark_from_string(((type_fields*)(td->fields.array[i]))->name); + fld->child[i]->field_type->element_name + = g_strdup(((type_fields*)(td->fields.array[i]))->name); } fld->child[i]->offset_root = -1; @@ -337,25 +313,43 @@ void constructTypeAndFields(LttFacility * fac, type_descriptor * td, LttType * lookup_named_type(LttFacility *fac, type_descriptor * td) { - GQuark name = g_quark_from_string(td->type_name); + LttType * lttType = NULL; + unsigned int i=0; + gchar * name; + + if(td->type_name){ + for(i=0;inamed_types_number; i++){ + if(fac->named_types[i] == NULL) break; + name = fac->named_types[i]->type_name; + if(g_ascii_strcasecmp(name, td->type_name)==0){ + lttType = fac->named_types[i]; + // if(lttType->element_name) g_free(lttType->element_name); + // lttType->element_name = NULL; + break; + } + } + } - LttType *type = g_datalist_get_data(fac->named_types_by_name, name); - - if(type == NULL){ - type = g_new(LttType,1); - type->type_name = name; - g_datalist_set_data_full(fac->named_types, name, - type, freeLttNamedType); - type->type_class = td->type; - if(td->fmt) type->fmt = g_strdup(td->fmt); - else type->fmt = NULL; - type->size = td->size; - type->enum_strings = NULL; - type->element_type = NULL; - type->element_number = 0; + if(!lttType){ + lttType = g_new(LttType,1); + lttType->type_class = td->type; + if(td->fmt) lttType->fmt = g_strdup(td->fmt); + else lttType->fmt = NULL; + lttType->size = td->size; + lttType->enum_strings = NULL; + lttType->element_type = NULL; + lttType->element_number = 0; + lttType->element_name = NULL; + if(td->type_name){ + lttType->type_name = g_strdup(td->type_name); + fac->named_types[i] = lttType; /* i is initialized, checked. */ + } + else{ + lttType->type_name = NULL; + } } - return type; + return lttType; } @@ -365,12 +359,16 @@ LttType * lookup_named_type(LttFacility *fac, type_descriptor * td) * if usage count = 0, release the memory *Input params * f : facility that will be closed + *Return value + * int : usage count ?? status ****************************************************************************/ -void ltt_facility_close(LttFacility *f) +int ltt_facility_close(LttFacility *f) { //release the memory it occupied freeFacility(f); + + return 0; } /***************************************************************************** @@ -379,22 +377,30 @@ void ltt_facility_close(LttFacility *f) void freeFacility(LttFacility * fac) { - guint i; - LttEventType *et; + unsigned int i; + g_free(fac->name); //free facility name - for(i=0; ievents->len; i++) { - et = &g_array_index (fac->events, LttEventType, i); - freeEventtype(et); + //free event types + for(i=0;ievent_number;i++){ + freeEventtype(fac->events[i]); } - g_array_free(fac->events); + g_free(fac->events); - g_datalist_clear(fac->named_types); + //free all named types + for(i=0;inamed_types_number;i++){ + freeLttNamedType(fac->named_types[i]); + fac->named_types[i] = NULL; + } + g_free(fac->named_types); + //free the facility itself + g_free(fac); } void freeEventtype(LttEventType * evType) { LttType * root_type; + g_free(evType->name); if(evType->description) g_free(evType->description); if(evType->root_field){ @@ -402,10 +408,14 @@ void freeEventtype(LttEventType * evType) freeLttField(evType->root_field); freeLttType(&root_type); } + + g_free(evType); } void freeLttNamedType(LttType * type) { + g_free(type->type_name); + type->type_name = NULL; freeLttType(&type); } @@ -413,12 +423,16 @@ void freeLttType(LttType ** type) { unsigned int i; if(*type == NULL) return; - //if((*type)->type_name){ - // return; //this is a named type - //} + if((*type)->type_name){ + return; //this is a named type + } + if((*type)->element_name) + g_free((*type)->element_name); if((*type)->fmt) g_free((*type)->fmt); if((*type)->enum_strings){ + for(i=0;i<(*type)->element_number;i++) + g_free((*type)->enum_strings[i]); g_free((*type)->enum_strings); } @@ -458,12 +472,12 @@ void freeLttField(LttField * fld) *Function name * ltt_facility_name : obtain the facility's name *Input params - * f : the facility + * f : the facility that will be closed *Return value - * GQuark : the facility's name + * char * : the facility's name ****************************************************************************/ -GQuark ltt_facility_name(LttFacility *f) +gchar *ltt_facility_name(LttFacility *f) { return f->name; } @@ -472,7 +486,7 @@ GQuark ltt_facility_name(LttFacility *f) *Function name * ltt_facility_checksum : obtain the facility's checksum *Input params - * f : the facility + * f : the facility that will be closed *Return value * LttChecksum : the checksum of the facility ****************************************************************************/ @@ -491,9 +505,9 @@ LttChecksum ltt_facility_checksum(LttFacility *f) * : the base id of the facility ****************************************************************************/ -guint ltt_facility_id(LttFacility *f) +unsigned ltt_facility_base_id(LttFacility *f) { - return f->id; + return f->base_id; } /***************************************************************************** @@ -502,12 +516,12 @@ guint ltt_facility_id(LttFacility *f) *Input params * f : the facility that will be closed *Return value - * : the number of the event types + * unsigned : the number of the event types ****************************************************************************/ -guint ltt_facility_eventtype_number(LttFacility *f) +unsigned ltt_facility_eventtype_number(LttFacility *f) { - return (f->events->len); + return (f->event_number); } /***************************************************************************** @@ -520,10 +534,9 @@ guint ltt_facility_eventtype_number(LttFacility *f) * LttEventType * : the event type required ****************************************************************************/ -LttEventType *ltt_facility_eventtype_get(LttFacility *f, guint8 i) +LttEventType *ltt_facility_eventtype_get(LttFacility *f, unsigned i) { - g_assert(i < f->events->len); - return &g_array_index(f->events, LttEventType, i); + return f->events[i]; } /***************************************************************************** @@ -538,8 +551,18 @@ LttEventType *ltt_facility_eventtype_get(LttFacility *f, guint8 i) * LttEventType * : the event type required ****************************************************************************/ -LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, GQuark name) +LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, gchar *name) { - LttEventType *et = g_datalist_get_data(fac->events_by_name, name); + unsigned int i; + LttEventType * ev = NULL; + + for(i=0;ievent_number;i++){ + LttEventType *iter_ev = f->events[i]; + if(g_ascii_strcasecmp(iter_ev->name, name) == 0) { + ev = iter_ev; + break; + } + } + return ev; } diff --git a/ltt/branches/poly/ltt-newlib/facility.h b/ltt/branches/poly/ltt-oldlib/facility.h similarity index 89% rename from ltt/branches/poly/ltt-newlib/facility.h rename to ltt/branches/poly/ltt-oldlib/facility.h index 7398d659..290dca7b 100644 --- a/ltt/branches/poly/ltt-newlib/facility.h +++ b/ltt/branches/poly/ltt-oldlib/facility.h @@ -25,12 +25,12 @@ with a facility are released when the trace is closed. Each facility is characterized by its name and checksum. */ -GQuark ltt_facility_name(LttFacility *f); +gchar *ltt_facility_name(LttFacility *f); LttChecksum ltt_facility_checksum(LttFacility *f); /* open facility */ -void ltt_facility_open(LttTrace * t, GQuark facility_name); +void ltt_facility_open(LttTrace * t, gchar * facility_name); /* Discover the event types within the facility. The event type integer id relative to the trace is from 0 to nb_event_types - 1. The event @@ -43,13 +43,9 @@ unsigned ltt_facility_eventtype_number(LttFacility *f); LttEventType *ltt_facility_eventtype_get(LttFacility *f, unsigned i); -LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, GQuark name); +LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, gchar *name); int ltt_facility_close(LttFacility *f); -/* Reserved facility names */ - -static const char *ltt_facility_name_core = "core"; - #endif // FACILITY_H diff --git a/ltt/branches/poly/ltt-oldlib/ltt-private.h b/ltt/branches/poly/ltt-oldlib/ltt-private.h new file mode 100644 index 00000000..05c18c0f --- /dev/null +++ b/ltt/branches/poly/ltt-oldlib/ltt-private.h @@ -0,0 +1,252 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2003-2004 Xiangxiu Yang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef LTT_PRIVATE_H +#define LTT_PRIVATE_H + +#include +#include +#include + +#define LTT_PACKED_STRUCT __attribute__ ((packed)) + +/* enumeration definition */ + +typedef enum _BuildinEvent{ + TRACE_FACILITY_LOAD = 0, + TRACE_BLOCK_START = 17, + TRACE_BLOCK_END = 18, + TRACE_TIME_HEARTBEAT= 19 +} BuildinEvent; + + +/* structure definition */ + +typedef struct _FacilityLoad{ + gchar * name; + LttChecksum checksum; + guint32 base_code; +} LTT_PACKED_STRUCT FacilityLoad; + +typedef struct _BlockStart { + LttTime time; //Time stamp of this block + LttCycleCount cycle_count; //cycle count of the event + guint32 block_id; //block id +} LTT_PACKED_STRUCT BlockStart; + +typedef struct _BlockEnd { + LttTime time; //Time stamp of this block + LttCycleCount cycle_count; //cycle count of the event + guint32 block_id; //block id +} LTT_PACKED_STRUCT BlockEnd; + +typedef struct _TimeHeartbeat { + LttTime time; //Time stamp of this block + LttCycleCount cycle_count; //cycle count of the event +} LTT_PACKED_STRUCT TimeHeartbeat; + + +struct _LttType{ + gchar * type_name; //type name if it is a named type + gchar * element_name; //elements name of the struct + gchar * fmt; + unsigned int size; + LttTypeEnum type_class; //which type + gchar ** enum_strings; //for enum labels + struct _LttType ** element_type; //for array, sequence and struct + unsigned element_number; //the number of elements + //for enum, array, sequence and structure +}; + +struct _LttEventType{ + gchar * name; + gchar * description; + int index; //id of the event type within the facility + LttFacility * facility; //the facility that contains the event type + LttField * root_field; //root field + unsigned int latest_block; //the latest block using the event type + unsigned int latest_event; //the latest event using the event type +}; + +struct _LttEvent{ + guint16 event_id; + guint32 time_delta; + LttTime event_time; + LttCycleCount event_cycle_count; + LttTracefile * tracefile; + void * data; //event data + unsigned int which_block; //the current block of the event + unsigned int which_event; //the position of the event + /* This is a workaround for fast position seek */ + void * last_event_pos; + + LttTime prev_block_end_time; //the end time of previous block + LttTime prev_event_time; //the time of the previous event + LttCycleCount pre_cycle_count; //previous cycle count of the event + int count; //the number of overflow of cycle count + gint64 overflow_nsec; //precalculated nsec for overflows + TimeHeartbeat * last_heartbeat; //last heartbeat + + /* end of workaround */ +}; + + +struct _LttField{ + unsigned field_pos; //field position within its parent + LttType * field_type; //field type, if it is root field + //then it must be struct type + + off_t offset_root; //offset from the root, -1:uninitialized + short fixed_root; //offset fixed according to the root + //-1:uninitialized, 0:unfixed, 1:fixed + off_t offset_parent; //offset from the parent,-1:uninitialized + short fixed_parent; //offset fixed according to its parent + //-1:uninitialized, 0:unfixed, 1:fixed + // void * base_address; //base address of the field ???? + + int field_size; //>0: size of the field, + //0 : uncertain + //-1: uninitialize + int sequ_number_size; //the size of unsigned used to save the + //number of elements in the sequence + + int element_size; //the element size of the sequence + int field_fixed; //0: field has string or sequence + //1: field has no string or sequenc + //-1: uninitialize + + struct _LttField * parent; + struct _LttField ** child; //for array, sequence and struct: + //list of fields, it may have only one + //field if the element is not a struct + unsigned current_element; //which element is currently processed +}; + + +struct _LttFacility{ + gchar * name; //facility name + unsigned int event_number; //number of events in the facility + LttChecksum checksum; //checksum of the facility + guint32 base_id; //base id of the facility + LttEventType ** events; //array of event types + LttType ** named_types; + unsigned int named_types_number; +}; + +struct _LttTracefile{ + gchar * name; //tracefile name + LttTrace * trace; //trace containing the tracefile + int fd; //file descriptor + off_t file_size; //file size + unsigned block_size; //block_size + unsigned int block_number; //number of blocks in the file + unsigned int which_block; //which block the current block is + unsigned int which_event; //which event of the current block + //is currently processed + LttTime current_event_time; //time of the current event + BlockStart * a_block_start; //block start of the block- trace endian + BlockEnd * a_block_end; //block end of the block - trace endian + TimeHeartbeat * last_heartbeat; //last heartbeat + void * cur_event_pos; //the position of the current event + void * buffer; //the buffer containing the block + double nsec_per_cycle; //Nsec per cycle + guint64 one_overflow_nsec; //nsec for one overflow + gint64 overflow_nsec; //precalculated nsec for overflows + //can be negative to include value + //of block start cycle count. + //incremented at each overflow while + //reading. + //LttCycleCount cycles_per_nsec_reciprocal; // Optimisation for speed + unsigned cur_heart_beat_number; //current number of heart beat in the buf + LttCycleCount cur_cycle_count; //current cycle count of the event + void * last_event_pos; + + LttTime prev_block_end_time; //the end time of previous block + LttTime prev_event_time; //the time of the previous event + LttCycleCount pre_cycle_count; //previous cycle count of the event + unsigned int count; //the number of overflow of cycle count +}; + +struct _LttTrace{ + gchar * pathname; //the pathname of the trace + guint facility_number; //the number of facilities + guint control_tracefile_number; //the number of control files + guint per_cpu_tracefile_number; //the number of per cpu files + LttSystemDescription * system_description;//system description + + GPtrArray *control_tracefiles; //array of control tracefiles + GPtrArray *per_cpu_tracefiles; //array of per cpu tracefiles + GPtrArray *facilities; //array of facilities + gboolean reverse_byte_order; //must we reverse BO ? +}; + +struct _LttEventPosition{ + unsigned block_num; //block which contains the event + unsigned event_num; //event index in the block + unsigned event_offset; //event position in the block + LttTime event_time; //the time of the event + LttCycleCount event_cycle_count; //the cycle count of the event + unsigned heart_beat_number; //current number of heart beats + LttTracefile *tf; //tracefile containing the event + gboolean old_position; //flag to show if it is the position + //being remembered + /* This is a workaround for fast position seek */ + void * last_event_pos; + + LttTime prev_block_end_time; //the end time of previous block + LttTime prev_event_time; //the time of the previous event + LttCycleCount pre_cycle_count; //previous cycle count of the event + int count; //the number of overflow of cycle count + gint64 overflow_nsec; //precalculated nsec for overflows + TimeHeartbeat * last_heartbeat; //last heartbeat + /* end of workaround */ +}; + +/* The characteristics of the system on which the trace was obtained + is described in a LttSystemDescription structure. */ + +struct _LttSystemDescription { + gchar *description; + gchar *node_name; + gchar *domain_name; + unsigned nb_cpu; + LttArchSize size; + LttArchEndian endian; + gchar *kernel_name; + gchar *kernel_release; + gchar *kernel_version; + gchar *machine; + gchar *processor; + gchar *hardware_platform; + gchar *operating_system; + unsigned ltt_major_version; + unsigned ltt_minor_version; + unsigned ltt_block_size; + LttTime trace_start; + LttTime trace_end; +}; + +/***************************************************************************** + macro for size of some data types + *****************************************************************************/ +#define EVENT_ID_SIZE sizeof(guint16) +#define TIME_DELTA_SIZE sizeof(guint32) +#define EVENT_HEADER_SIZE (EVENT_ID_SIZE + TIME_DELTA_SIZE) + + +#endif /* LTT_PRIVATE_H */ diff --git a/ltt/branches/poly/ltt-newlib/ltt-types.h b/ltt/branches/poly/ltt-oldlib/ltt-types.h similarity index 100% rename from ltt/branches/poly/ltt-newlib/ltt-types.h rename to ltt/branches/poly/ltt-oldlib/ltt-types.h diff --git a/ltt/branches/poly/ltt-newlib/ltt.h b/ltt/branches/poly/ltt-oldlib/ltt.h similarity index 96% rename from ltt/branches/poly/ltt-newlib/ltt.h rename to ltt/branches/poly/ltt-oldlib/ltt.h index 4434f8cf..5651702c 100644 --- a/ltt/branches/poly/ltt-newlib/ltt.h +++ b/ltt/branches/poly/ltt-oldlib/ltt.h @@ -87,7 +87,7 @@ typedef struct _LttSystemDescription LttSystemDescription; /* Checksums are used to differentiate facilities which have the same name but differ. */ -//typedef guint32 LttChecksum; +typedef guint32 LttChecksum; /* Events are usually stored with the easily obtained CPU clock cycle count, @@ -127,8 +127,7 @@ typedef enum _LttArchEndian } LttArchEndian; typedef enum _LttTypeEnum -{ LTT_INT, LTT_UINT, LTT_POINTER, LTT_LONG, LTT_ULONG, LTT_SIZE_T, - LTT_SSIZE_T, LTT_OFF_T, LTT_FLOAT, LTT_STRING, LTT_ENUM, LTT_ARRAY, +{ LTT_INT, LTT_UINT, LTT_FLOAT, LTT_STRING, LTT_ENUM, LTT_ARRAY, LTT_SEQUENCE, LTT_STRUCT, LTT_UNION } LttTypeEnum; diff --git a/ltt/branches/poly/ltt-newlib/parser.c b/ltt/branches/poly/ltt-oldlib/parser.c similarity index 100% rename from ltt/branches/poly/ltt-newlib/parser.c rename to ltt/branches/poly/ltt-oldlib/parser.c diff --git a/ltt/branches/poly/ltt-newlib/parser.h b/ltt/branches/poly/ltt-oldlib/parser.h similarity index 100% rename from ltt/branches/poly/ltt-newlib/parser.h rename to ltt/branches/poly/ltt-oldlib/parser.h diff --git a/ltt/branches/poly/ltt-newlib/time.h b/ltt/branches/poly/ltt-oldlib/time.h similarity index 100% rename from ltt/branches/poly/ltt-newlib/time.h rename to ltt/branches/poly/ltt-oldlib/time.h diff --git a/ltt/branches/poly/ltt-newlib/trace.h b/ltt/branches/poly/ltt-oldlib/trace.h similarity index 91% rename from ltt/branches/poly/ltt-newlib/trace.h rename to ltt/branches/poly/ltt-oldlib/trace.h index 1956bb78..a2360bb5 100644 --- a/ltt/branches/poly/ltt-newlib/trace.h +++ b/ltt/branches/poly/ltt-oldlib/trace.h @@ -21,10 +21,6 @@ #include - -extern GQuark LTT_FACILITY_NAME_HEARTBEAT, - LTT_EVENT_NAME_HEARTBEAT; - /* A trace is specified as a pathname to the directory containing all the associated data (control tracefiles, per cpu tracefiles, event descriptions...). @@ -124,21 +120,16 @@ unsigned ltt_tracefile_block_number(LttTracefile *tf); /* Seek to the first event of the trace with time larger or equal to time */ -int ltt_tracefile_seek_time(LttTracefile *t, LttTime time); +void ltt_tracefile_seek_time(LttTracefile *t, LttTime time); /* Seek to the first event with position equal or larger to ep */ -int ltt_tracefile_seek_position(LttTracefile *t, +void ltt_tracefile_seek_position(LttTracefile *t, const LttEventPosition *ep); /* Read the next event */ -int ltt_tracefile_read(LttTracefile *t); - -/* ltt_tracefile_read cut down in pieces */ -int ltt_tracefile_read_seek(LttTracefile *t); -int ltt_tracefile_read_update_event(LttTracefile *t); -int ltt_tracefile_read_op(LttTracefile *t); +LttEvent *ltt_tracefile_read(LttTracefile *t, LttEvent *event); /* open tracefile */ @@ -154,7 +145,9 @@ gint ltt_tracefile_open_control(LttTrace *t, gchar * control_name); void getDataEndianType(LttArchSize * size, LttArchEndian * endian); /* get an integer number */ -gint64 get_int(gboolean reverse_byte_order, gint size, void *data); + +gint64 getIntNumber(gboolean reverse_byte_order, int size1, void *evD); + /* get the node name of the system */ @@ -182,6 +175,4 @@ void ltt_tracefile_copy(LttTracefile *dest, const LttTracefile *src); void get_absolute_pathname(const gchar *pathname, gchar * abs_pathname); - - #endif // TRACE_H diff --git a/ltt/branches/poly/ltt-oldlib/tracefile.c b/ltt/branches/poly/ltt-oldlib/tracefile.c new file mode 100644 index 00000000..a111e41f --- /dev/null +++ b/ltt/branches/poly/ltt-oldlib/tracefile.c @@ -0,0 +1,1754 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2003-2004 Xiangxiu Yang, Mathieu Desnoyers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// For realpath +#include +#include + + +#include "parser.h" +#include +#include "ltt-private.h" +#include +#include +#include +#include +#include + +#ifndef g_open +#define g_open open +#endif + + +#define DIR_NAME_SIZE 256 +#define __UNUSED__ __attribute__((__unused__)) + +#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) +#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) + +#define g_close close + +/* obtain the time of an event */ + +static inline LttTime getEventTime(LttTracefile * tf); + + +/* set the offset of the fields belonging to the event, + need the information of the archecture */ +void setFieldsOffset(LttTracefile *tf,LttEventType *evT,void *evD,LttTrace *t); + +/* get the size of the field type according to the archtecture's + size and endian type(info of the archecture) */ +static inline gint getFieldtypeSize(LttTracefile * tf, + LttEventType * evT, gint offsetRoot, + gint offsetParent, LttField *fld, void *evD, LttTrace* t); + +/* read a fixed size or a block information from the file (fd) */ +int readFile(int fd, void * buf, size_t size, gchar * mesg); +int readBlock(LttTracefile * tf, int whichBlock); + +/* calculate cycles per nsec for current block */ +void getCyclePerNsec(LttTracefile * t); + +/* reinitialize the info of the block which is already in the buffer */ +void updateTracefile(LttTracefile * tf); + +/* go to the next event */ +int skipEvent(LttTracefile * t); + + +/* Functions to parse system.xml file (using glib xml parser) */ +static void parser_start_element (GMarkupParseContext __UNUSED__ *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + int i=0; + LttSystemDescription* des = (LttSystemDescription* )user_data; + if(strcmp("system", element_name)){ + *error = g_error_new(G_MARKUP_ERROR, + G_LOG_LEVEL_WARNING, + "This is not system.xml file"); + return; + } + + while(attribute_names[i]){ + if(strcmp("node_name", attribute_names[i])==0){ + des->node_name = g_strdup(attribute_values[i]); + }else if(strcmp("domainname", attribute_names[i])==0){ + des->domain_name = g_strdup(attribute_values[i]); + }else if(strcmp("cpu", attribute_names[i])==0){ + des->nb_cpu = atoi(attribute_values[i]); + }else if(strcmp("arch_size", attribute_names[i])==0){ + if(strcmp(attribute_values[i],"LP32") == 0) des->size = LTT_LP32; + else if(strcmp(attribute_values[i],"ILP32") == 0) des->size = LTT_ILP32; + else if(strcmp(attribute_values[i],"LP64") == 0) des->size = LTT_LP64; + else if(strcmp(attribute_values[i],"ILP64") == 0) des->size = LTT_ILP64; + else if(strcmp(attribute_values[i],"UNKNOWN") == 0) des->size = LTT_UNKNOWN; + }else if(strcmp("endian", attribute_names[i])==0){ + if(strcmp(attribute_values[i],"LITTLE_ENDIAN") == 0) + des->endian = LTT_LITTLE_ENDIAN; + else if(strcmp(attribute_values[i],"BIG_ENDIAN") == 0) + des->endian = LTT_BIG_ENDIAN; + }else if(strcmp("kernel_name", attribute_names[i])==0){ + des->kernel_name = g_strdup(attribute_values[i]); + }else if(strcmp("kernel_release", attribute_names[i])==0){ + des->kernel_release = g_strdup(attribute_values[i]); + }else if(strcmp("kernel_version", attribute_names[i])==0){ + des->kernel_version = g_strdup(attribute_values[i]); + }else if(strcmp("machine", attribute_names[i])==0){ + des->machine = g_strdup(attribute_values[i]); + }else if(strcmp("processor", attribute_names[i])==0){ + des->processor = g_strdup(attribute_values[i]); + }else if(strcmp("hardware_platform", attribute_names[i])==0){ + des->hardware_platform = g_strdup(attribute_values[i]); + }else if(strcmp("operating_system", attribute_names[i])==0){ + des->operating_system = g_strdup(attribute_values[i]); + }else if(strcmp("ltt_major_version", attribute_names[i])==0){ + des->ltt_major_version = atoi(attribute_values[i]); + }else if(strcmp("ltt_minor_version", attribute_names[i])==0){ + des->ltt_minor_version = atoi(attribute_values[i]); + }else if(strcmp("ltt_block_size", attribute_names[i])==0){ + des->ltt_block_size = atoi(attribute_values[i]); + }else{ + *error = g_error_new(G_MARKUP_ERROR, + G_LOG_LEVEL_WARNING, + "Not a valid attribute"); + return; + } + i++; + } +} + +static void parser_characters (GMarkupParseContext __UNUSED__ *context, + const gchar *text, + gsize __UNUSED__ text_len, + gpointer user_data, + GError __UNUSED__ **error) +{ + LttSystemDescription* des = (LttSystemDescription* )user_data; + des->description = g_strdup(text); +} + + +/***************************************************************************** + *Function name + * ltt_tracefile_open : open a trace file, construct a LttTracefile + *Input params + * t : the trace containing the tracefile + * fileName : path name of the trace file + *Return value + * : a pointer to a tracefile + ****************************************************************************/ + +LttTracefile* ltt_tracefile_open(LttTrace * t, gchar * fileName) +{ + LttTracefile * tf; + struct stat lTDFStat; /* Trace data file status */ + + tf = g_new(LttTracefile, 1); + + //open the file + tf->name = g_strdup(fileName); + tf->trace = t; + tf->fd = g_open(fileName, O_RDONLY, 0); + if(tf->fd < 0){ + g_warning("Unable to open input data file %s\n", fileName); + g_free(tf->name); + g_free(tf); + return NULL; + } + + // Get the file's status + if(fstat(tf->fd, &lTDFStat) < 0){ + g_warning("Unable to get the status of the input data file %s\n", fileName); + g_free(tf->name); + g_close(tf->fd); + g_free(tf); + return NULL; + } + + // Is the file large enough to contain a trace + if(lTDFStat.st_size < (off_t)(sizeof(BlockStart) + EVENT_HEADER_SIZE)){ + g_print("The input data file %s does not contain a trace\n", fileName); + g_free(tf->name); + g_close(tf->fd); + g_free(tf); + return NULL; + } + + //store the size of the file + tf->file_size = lTDFStat.st_size; + tf->block_size = t->system_description->ltt_block_size; + tf->block_number = tf->file_size / tf->block_size; + tf->which_block = 0; + + //allocate memory to contain the info of a block + tf->buffer = (void *) g_new(gchar, t->system_description->ltt_block_size); + + //read the first block + if(readBlock(tf,1)) exit(1); + + return tf; +} + + +/***************************************************************************** + *Open control and per cpu tracefiles + ****************************************************************************/ + +void ltt_tracefile_open_cpu(LttTrace *t, gchar * tracefile_name) +{ + LttTracefile * tf; + tf = ltt_tracefile_open(t,tracefile_name); + if(!tf) return; + t->per_cpu_tracefile_number++; + g_ptr_array_add(t->per_cpu_tracefiles, tf); +} + +gint ltt_tracefile_open_control(LttTrace *t, gchar * control_name) +{ + LttTracefile * tf; + LttEvent ev; + LttFacility * f; + void * pos; + FacilityLoad fLoad; + unsigned int i; + + tf = ltt_tracefile_open(t,control_name); + if(!tf) { + g_warning("ltt_tracefile_open_control : bad file descriptor"); + return -1; + } + t->control_tracefile_number++; + g_ptr_array_add(t->control_tracefiles,tf); + + //parse facilities tracefile to get base_id + if(strcmp(&control_name[strlen(control_name)-10],"facilities") ==0){ + while(1){ + if(!ltt_tracefile_read(tf,&ev)) return 0; // end of file + + if(ev.event_id == TRACE_FACILITY_LOAD){ + pos = ev.data; + fLoad.name = (gchar*)pos; + fLoad.checksum = *(LttChecksum*)(pos + strlen(fLoad.name)); + fLoad.base_code = *(guint32 *)(pos + strlen(fLoad.name) + sizeof(LttChecksum)); + + for(i=0;ifacility_number;i++){ + f = (LttFacility*)g_ptr_array_index(t->facilities,i); + if(strcmp(f->name,fLoad.name)==0 && fLoad.checksum==f->checksum){ + f->base_id = fLoad.base_code; + break; + } + } + if(i==t->facility_number) { + g_warning("Facility: %s, checksum: %u is not found", + fLoad.name,(unsigned int)fLoad.checksum); + return -1; + } + }else if(ev.event_id == TRACE_BLOCK_START){ + continue; + }else if(ev.event_id == TRACE_BLOCK_END){ + break; + }else { + g_warning("Not valid facilities trace file"); + return -1; + } + } + } + return 0; +} + +/***************************************************************************** + *Function name + * ltt_tracefile_close: close a trace file, + *Input params + * t : tracefile which will be closed + ****************************************************************************/ + +void ltt_tracefile_close(LttTracefile *t) +{ + g_free(t->name); + g_free(t->buffer); + close(t->fd); + g_free(t); +} + + +/***************************************************************************** + *Get system information + ****************************************************************************/ +gint getSystemInfo(LttSystemDescription* des, gchar * pathname) +{ + int fd; + GIOChannel *iochan; + gchar *buf = NULL; + gsize length; + + GMarkupParseContext * context; + GError * error = NULL; + GMarkupParser markup_parser = + { + parser_start_element, + NULL, + parser_characters, + NULL, /* passthrough */ + NULL /* error */ + }; + + fd = g_open(pathname, O_RDONLY, 0); + if(fd == -1){ + g_warning("Can not open file : %s\n", pathname); + return -1; + } + + iochan = g_io_channel_unix_new(fd); + + context = g_markup_parse_context_new(&markup_parser, 0, des,NULL); + + //while(fgets(buf,DIR_NAME_SIZE, fp) != NULL){ + while(g_io_channel_read_line(iochan, &buf, &length, NULL, &error) + != G_IO_STATUS_EOF) { + + if(error != NULL) { + g_warning("Can not read xml file: \n%s\n", error->message); + g_error_free(error); + } + if(!g_markup_parse_context_parse(context, buf, length, &error)){ + if(error != NULL) { + g_warning("Can not parse xml file: \n%s\n", error->message); + g_error_free(error); + } + g_markup_parse_context_free(context); + + g_io_channel_shutdown(iochan, FALSE, &error); /* No flush */ + if(error != NULL) { + g_warning("Can not close file: \n%s\n", error->message); + g_error_free(error); + } + + close(fd); + return -1; + } + } + g_markup_parse_context_free(context); + + g_io_channel_shutdown(iochan, FALSE, &error); /* No flush */ + if(error != NULL) { + g_warning("Can not close file: \n%s\n", error->message); + g_error_free(error); + } + + g_close(fd); + + g_free(buf); + return 0; +} + +/***************************************************************************** + *The following functions get facility/tracefile information + ****************************************************************************/ + +gint getFacilityInfo(LttTrace *t, gchar* eventdefs) +{ + GDir * dir; + const gchar * name; + unsigned int i,j; + LttFacility * f; + LttEventType * et; + gchar fullname[DIR_NAME_SIZE]; + GError * error = NULL; + + dir = g_dir_open(eventdefs, 0, &error); + + if(error != NULL) { + g_warning("Can not open directory: %s, %s\n", eventdefs, error->message); + g_error_free(error); + return -1; + } + + while((name = g_dir_read_name(dir)) != NULL){ + if(!g_pattern_match_simple("*.xml", name)) continue; + strcpy(fullname,eventdefs); + strcat(fullname,name); + ltt_facility_open(t,fullname); + } + g_dir_close(dir); + + for(j=0;jfacility_number;j++){ + f = (LttFacility*)g_ptr_array_index(t->facilities, j); + for(i=0; ievent_number; i++){ + et = f->events[i]; + setFieldsOffset(NULL, et, NULL, t); + } + } + return 0; +} + +gint getControlFileInfo(LttTrace *t, gchar* control) +{ + GDir * dir; + const gchar *name; + gchar fullname[DIR_NAME_SIZE]; + GError * error = NULL; + + dir = g_dir_open(control, 0, &error); + + if(error != NULL) { + g_warning("Can not open directory: %s, %s\n", control, error->message); + g_error_free(error); + return -1; + } + + while((name = g_dir_read_name(dir)) != NULL){ + if(strcmp(name,"facilities") != 0 && + strcmp(name,"interrupts") != 0 && + strcmp(name,"processes") != 0) continue; + + strcpy(fullname,control); + strcat(fullname,name); + if(ltt_tracefile_open_control(t,fullname)) { + g_dir_close(dir); + return -1; + } + } + g_dir_close(dir); + return 0; +} + +gint getCpuFileInfo(LttTrace *t, char* cpu) +{ + GDir * dir; + const gchar * name; + gchar fullname[DIR_NAME_SIZE]; + GError * error = NULL; + + dir = g_dir_open(cpu, 0, &error); + + if(error != NULL) { + g_warning("Can not open directory: %s, %s\n", cpu, error->message); + g_error_free(error); + return -1; + } + + while((name = g_dir_read_name(dir)) != NULL){ + if(strcmp(name,".svn") != 0){ /* . and .. already excluded */ + strcpy(fullname,cpu); + strcat(fullname,name); + ltt_tracefile_open_cpu(t,fullname); + }else continue; + } + g_dir_close(dir); + return 0; +} + +/***************************************************************************** + *A trace is specified as a pathname to the directory containing all the + *associated data (control tracefiles, per cpu tracefiles, event + *descriptions...). + * + *When a trace is closed, all the associated facilities, types and fields + *are released as well. + */ + + +/**************************************************************************** + * get_absolute_pathname + * + * return the unique pathname in the system + * + * MD : Fixed this function so it uses realpath, dealing well with + * forgotten cases (.. were not used correctly before). + * + ****************************************************************************/ +void get_absolute_pathname(const gchar *pathname, gchar * abs_pathname) +{ + abs_pathname[0] = '\0'; + + if ( realpath (pathname, abs_pathname) != NULL) + return; + else + { + /* error, return the original path unmodified */ + strcpy(abs_pathname, pathname); + return; + } + return; +} + +LttTrace *ltt_trace_open(const gchar *pathname) +{ + LttTrace * t; + LttSystemDescription * sys_description; + gchar eventdefs[DIR_NAME_SIZE]; + gchar info[DIR_NAME_SIZE]; + gchar control[DIR_NAME_SIZE]; + gchar cpu[DIR_NAME_SIZE]; + gchar tmp[DIR_NAME_SIZE]; + gchar abs_path[DIR_NAME_SIZE]; + gboolean has_slash = FALSE; + + get_absolute_pathname(pathname, abs_path); + //establish the pathname to different directories + if(abs_path[strlen(abs_path)-1] == '/')has_slash = TRUE; + strcpy(eventdefs,abs_path); + if(!has_slash)strcat(eventdefs,"/"); + strcat(eventdefs,"eventdefs/"); + + strcpy(info,abs_path); + if(!has_slash)strcat(info,"/"); + strcat(info,"info/"); + + strcpy(control,abs_path); + if(!has_slash)strcat(control,"/"); + strcat(control,"control/"); + + strcpy(cpu,abs_path); + if(!has_slash)strcat(cpu,"/"); + strcat(cpu,"cpu/"); + + //new trace + sys_description = g_new(LttSystemDescription, 1); + t = g_new(LttTrace, 1); + t->pathname = g_strdup(abs_path); + t->facility_number = 0; + t->control_tracefile_number = 0; + t->per_cpu_tracefile_number = 0; + t->system_description = sys_description; + t->control_tracefiles = g_ptr_array_new(); + t->per_cpu_tracefiles = g_ptr_array_new(); + t->facilities = g_ptr_array_new(); + //getDataEndianType(&(t->my_arch_size), &(t->my_arch_endian)); + + //get system description + strcpy(tmp,info); + strcat(tmp,"system.xml"); + if(getSystemInfo(sys_description, tmp)) { + g_ptr_array_free(t->facilities, TRUE); + g_ptr_array_free(t->per_cpu_tracefiles, TRUE); + g_ptr_array_free(t->control_tracefiles, TRUE); + g_free(sys_description); + g_free(t->pathname); + g_free(t); + return NULL; + } + + /* Set the reverse byte order between trace and reader */ + if(sys_description->endian == LTT_LITTLE_ENDIAN + && G_BYTE_ORDER != G_LITTLE_ENDIAN) { + t->reverse_byte_order = 1; + } else if(sys_description->endian == LTT_BIG_ENDIAN + && G_BYTE_ORDER != G_BIG_ENDIAN) { + t->reverse_byte_order = 1; + } else t->reverse_byte_order = 0; + + //get facilities info + if(getFacilityInfo(t,eventdefs)) { + g_ptr_array_free(t->facilities, TRUE); + g_ptr_array_free(t->per_cpu_tracefiles, TRUE); + g_ptr_array_free(t->control_tracefiles, TRUE); + g_free(sys_description); + g_free(t->pathname); + g_free(t); + return NULL; + } + + //get control tracefile info + getControlFileInfo(t,control); + /* + if(getControlFileInfo(t,control)) { + g_ptr_array_free(t->facilities, TRUE); + g_ptr_array_free(t->per_cpu_tracefiles, TRUE); + g_ptr_array_free(t->control_tracefiles, TRUE); + g_free(sys_description); + g_free(t->pathname); + g_free(t); + return NULL; + }*/ // With fatal error + + //get cpu tracefile info + if(getCpuFileInfo(t,cpu)) { + g_ptr_array_free(t->facilities, TRUE); + g_ptr_array_free(t->per_cpu_tracefiles, TRUE); + g_ptr_array_free(t->control_tracefiles, TRUE); + g_free(sys_description); + g_free(t->pathname); + g_free(t); + return NULL; + } + + return t; +} + +char * ltt_trace_name(LttTrace *t) +{ + return t->pathname; +} + + +/****************************************************************************** + * When we copy a trace, we want all the opening actions to happen again : + * the trace will be reopened and totally independant from the original. + * That's why we call ltt_trace_open. + *****************************************************************************/ +LttTrace *ltt_trace_copy(LttTrace *self) +{ + return ltt_trace_open(self->pathname); +} + +void ltt_trace_close(LttTrace *t) +{ + unsigned int i; + LttTracefile * tf; + LttFacility * f; + + g_free(t->pathname); + + //free system_description + g_free(t->system_description->description); + g_free(t->system_description->node_name); + g_free(t->system_description->domain_name); + g_free(t->system_description->kernel_name); + g_free(t->system_description->kernel_release); + g_free(t->system_description->kernel_version); + g_free(t->system_description->machine); + g_free(t->system_description->processor); + g_free(t->system_description->hardware_platform); + g_free(t->system_description->operating_system); + g_free(t->system_description); + + //free control_tracefiles + for(i=0;icontrol_tracefile_number;i++){ + tf = (LttTracefile*)g_ptr_array_index(t->control_tracefiles,i); + ltt_tracefile_close(tf); + } + g_ptr_array_free(t->control_tracefiles, TRUE); + + //free per_cpu_tracefiles + for(i=0;iper_cpu_tracefile_number;i++){ + tf = (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles,i); + ltt_tracefile_close(tf); + } + g_ptr_array_free(t->per_cpu_tracefiles, TRUE); + + //free facilities + for(i=0;ifacility_number;i++){ + f = (LttFacility*)g_ptr_array_index(t->facilities,i); + ltt_facility_close(f); + } + g_ptr_array_free(t->facilities, TRUE); + + g_free(t); + + g_blow_chunks(); +} + + +/***************************************************************************** + *Get the system description of the trace + ****************************************************************************/ + +LttSystemDescription *ltt_trace_system_description(LttTrace *t) +{ + return t->system_description; +} + +/***************************************************************************** + * The following functions discover the facilities of the trace + ****************************************************************************/ + +unsigned ltt_trace_facility_number(LttTrace *t) +{ + return (unsigned)(t->facility_number); +} + +LttFacility *ltt_trace_facility_get(LttTrace *t, unsigned i) +{ + return (LttFacility*)g_ptr_array_index(t->facilities, i); +} + +/***************************************************************************** + *Function name + * ltt_trace_facility_find : find facilities in the trace + *Input params + * t : the trace + * name : facility name + *Output params + * position : position of the facility in the trace + *Return value + * : the number of facilities + ****************************************************************************/ + +unsigned ltt_trace_facility_find(LttTrace *t, char *name, unsigned *position) +{ + unsigned int i, count=0; + LttFacility * f; + for(i=0;ifacility_number;i++){ + f = (LttFacility*)g_ptr_array_index(t->facilities, i); + if(strcmp(f->name,name)==0){ + count++; + if(count==1) *position = i; + }else{ + if(count) break; + } + } + return count; +} + +/***************************************************************************** + * Functions to discover all the event types in the trace + ****************************************************************************/ + +unsigned ltt_trace_eventtype_number(LttTrace *t) +{ + unsigned int i; + unsigned count = 0; + unsigned int num = t->facility_number; + LttFacility * f; + + for(i=0;ifacilities, i); + count += f->event_number; + } + return count; +} + +/* FIXME : performances could be improved with a better design for this + * function : sequential search through a container has never been the + * best on the critical path. */ +LttFacility * ltt_trace_facility_by_id(LttTrace * trace, unsigned id) +{ + LttFacility * facility = NULL; + unsigned int i; + unsigned int num = trace->facility_number; + GPtrArray *facilities = trace->facilities; + + for(i=0;unlikely(ibase_id; + + if(likely(id >= base_id && + id < base_id + iter_facility->event_number)) { + facility = iter_facility; + break; + } else { + i++; + } + } + + return facility; +} + +LttEventType *ltt_trace_eventtype_get(LttTrace *t, unsigned evId) +{ + LttEventType *event_type; + + LttFacility * f; + f = ltt_trace_facility_by_id(t,evId); + + if(unlikely(!f)) event_type = NULL; + else event_type = f->events[evId - f->base_id]; + + return event_type; +} + +/***************************************************************************** + *There is one "per cpu" tracefile for each CPU, numbered from 0 to + *the maximum number of CPU in the system. When the number of CPU installed + *is less than the maximum, some positions are unused. There are also a + *number of "control" tracefiles (facilities, interrupts...). + ****************************************************************************/ +unsigned ltt_trace_control_tracefile_number(LttTrace *t) +{ + return t->control_tracefile_number; +} + +unsigned ltt_trace_per_cpu_tracefile_number(LttTrace *t) +{ + return t->per_cpu_tracefile_number; +} + +/***************************************************************************** + *It is possible to search for the tracefiles by name or by CPU position. + *The index within the tracefiles of the same type is returned if found + *and a negative value otherwise. + ****************************************************************************/ + +int ltt_trace_control_tracefile_find(LttTrace *t, const gchar *name) +{ + LttTracefile * tracefile; + unsigned int i; + for(i=0;icontrol_tracefile_number;i++){ + tracefile = (LttTracefile*)g_ptr_array_index(t->control_tracefiles, i); + if(strcmp(tracefile->name, name)==0)break; + } + if(i == t->control_tracefile_number) return -1; + return i; +} + +/* not really useful. We just have to know that cpu tracefiles + * comes before control tracefiles. + */ +int ltt_trace_per_cpu_tracefile_find(LttTrace *t, const gchar *name) +{ + LttTracefile * tracefile; + unsigned int i; + for(i=0;iper_cpu_tracefile_number;i++){ + tracefile = (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles, i); + if(strcmp(tracefile->name, name)==0)break; + } + if(i == t->per_cpu_tracefile_number) return -1; + return i; +} + +/***************************************************************************** + *Get a specific tracefile + ****************************************************************************/ + +LttTracefile *ltt_trace_control_tracefile_get(LttTrace *t, unsigned i) +{ + return (LttTracefile*)g_ptr_array_index(t->control_tracefiles, i); +} + +LttTracefile *ltt_trace_per_cpu_tracefile_get(LttTrace *t, unsigned i) +{ + return (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles, i); +} + +/***************************************************************************** + * Get the start time and end time of the trace + ****************************************************************************/ + +void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end) +{ + LttTime startSmall, startTmp, endBig, endTmp; + unsigned int i, j=0; + LttTracefile * tf; + + for(i=0;icontrol_tracefile_number;i++){ + tf = g_ptr_array_index(t->control_tracefiles, i); + readBlock(tf,1); + startTmp = ltt_get_time(t->reverse_byte_order, &tf->a_block_start->time); + readBlock(tf,tf->block_number); + endTmp = ltt_get_time(t->reverse_byte_order, &tf->a_block_end->time); + if(i==0){ + startSmall = startTmp; + endBig = endTmp; + j = 1; + continue; + } + if(ltt_time_compare(startSmall,startTmp) > 0) startSmall = startTmp; + if(ltt_time_compare(endBig,endTmp) < 0) endBig = endTmp; + } + + for(i=0;iper_cpu_tracefile_number;i++){ + tf = g_ptr_array_index(t->per_cpu_tracefiles, i); + readBlock(tf,1); + startTmp = ltt_get_time(t->reverse_byte_order, &tf->a_block_start->time); + readBlock(tf,tf->block_number); + endTmp = ltt_get_time(t->reverse_byte_order, &tf->a_block_end->time); + if(j == 0 && i==0){ + startSmall = startTmp; + endBig = endTmp; + continue; + } + if(ltt_time_compare(startSmall,startTmp) > 0) startSmall = startTmp; + if(ltt_time_compare(endBig,endTmp) < 0) endBig = endTmp; + } + + if(start != NULL) *start = startSmall; + if(end != NULL) *end = endBig; +} + + +/***************************************************************************** + *Get the name of a tracefile + ****************************************************************************/ + +char *ltt_tracefile_name(LttTracefile *tf) +{ + return tf->name; +} + +/***************************************************************************** + * Get the number of blocks in the tracefile + ****************************************************************************/ + +unsigned ltt_tracefile_block_number(LttTracefile *tf) +{ + return tf->block_number; +} + +/***************************************************************************** + *Function name + * ltt_tracefile_seek_time: seek to the first event of the trace with time + * larger or equal to time + *Input params + * t : tracefile + * time : criteria of the time + ****************************************************************************/ +void ltt_tracefile_find_time_block(LttTracefile *t, LttTime time, + int start_block, int end_block) +{ + int err, tmp_block, s, e; + int headTime; + int tailTime; + + err=readBlock(t,start_block); + if(err) g_error("Can not read tracefile: %s\n", t->name); + if(start_block == end_block)return; + + tailTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order, + &t->a_block_end->time), time); + if(tailTime >= 0) return; + + err=readBlock(t,end_block); + if(err) g_error("Can not read tracefile: %s\n", t->name); + if(start_block+1 == end_block)return; + + headTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order, + &t->a_block_start->time), time); + if(headTime <= 0 ) return; + + tmp_block = (end_block + start_block)/2; + err=readBlock(t,tmp_block); + if(err) g_error("Can not read tracefile: %s\n", t->name); + + headTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order, + &t->a_block_start->time), time); + tailTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order, + &t->a_block_end->time), time); + if(headTime <= 0 && tailTime >= 0) return; + + if(headTime > 0){ + s = start_block + 1; + e = tmp_block - 1; + if(s <= e) + ltt_tracefile_find_time_block(t, time, s, e); + else return; + } + + if(tailTime < 0){ + s = tmp_block + 1; + e = end_block - 1; + if(s <= e) + ltt_tracefile_find_time_block(t, time, s, e); + else return; + } +} + +void ltt_tracefile_backward_find_time_block(LttTracefile *t, LttTime time) +{ + int t_time, h_time, err; + err=readBlock(t,t->which_block-1); + if(err) g_error("Can not read tracefile: %s\n", t->name); + h_time = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order, + &t->a_block_start->time), time); + t_time = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order, + &t->a_block_end->time), time); + if(h_time == 0){ + int tmp; + if(t->which_block == 1) return; + err=readBlock(t,t->which_block-1); + if(err) g_error("Can not read tracefile: %s\n", t->name); + tmp = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order, + &t->a_block_end->time), time); + if(tmp == 0) return ltt_tracefile_seek_time(t, time); + err=readBlock(t,t->which_block+1); + if(err) g_error("Can not read tracefile: %s\n", t->name); + }else if(h_time > 0){ + ltt_tracefile_find_time_block(t, time, 1, t->which_block); + return ltt_tracefile_seek_time(t, time) ; + }else{ + if(t_time >= 0) return ltt_tracefile_seek_time(t, time); + err=readBlock(t,t->which_block+1); + if(err) g_error("Can not read tracefile: %s\n", t->name); + } +} + +void ltt_tracefile_seek_time(LttTracefile *t, LttTime time) +{ + int err; + LttTime lttTime; + int headTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order, + &t->a_block_start->time), time); + int tailTime = ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order, + &t->a_block_end->time), time); + LttEvent ev; + + if(headTime < 0 && tailTime > 0){ + if(ltt_time_compare(ltt_get_time(t->trace->reverse_byte_order, + &t->a_block_end->time), + t->current_event_time) !=0) { + lttTime = getEventTime(t); + err = ltt_time_compare(lttTime, time); + if(err > 0){ + if(t->which_event==2 || ltt_time_compare(t->prev_event_time,time)<0){ + return; + }else{ + updateTracefile(t); + return ltt_tracefile_seek_time(t, time); + } + }else if(err < 0){ + while(1){ + if(ltt_tracefile_read(t,&ev) == NULL) { + g_print("End of file\n"); + return; + } + lttTime = getEventTime(t); + err = ltt_time_compare(lttTime, time); + if(err >= 0)return; + } + }else return; + }else{//we are at the end of the block + updateTracefile(t); + return ltt_tracefile_seek_time(t, time); + } + }else if(headTime >= 0){ + if(t->which_block == 1){ + updateTracefile(t); + }else{ + if(ltt_time_compare(t->prev_block_end_time, time) >= 0 || + (t->prev_block_end_time.tv_sec == 0 && + t->prev_block_end_time.tv_nsec == 0 )){ + ltt_tracefile_backward_find_time_block(t, time); + }else{ + updateTracefile(t); + } + } + }else if(tailTime < 0){ + if(t->which_block != t->block_number){ + ltt_tracefile_find_time_block(t, time, t->which_block+1, t->block_number); + return ltt_tracefile_seek_time(t, time); + }else { + t->cur_event_pos = t->buffer + t->block_size; + g_print("End of file\n"); + return; + } + }else if(tailTime == 0){ + t->cur_event_pos = t->last_event_pos; + t->current_event_time = time; + t->cur_heart_beat_number = 0; + t->prev_event_time.tv_sec = 0; + t->prev_event_time.tv_nsec = 0; + return; + } +} + +/***************************************************************************** + * Seek to the first event with position equal or larger to ep + * + * Modified by Mathieu Desnoyers to used faster offset position instead of + * re-reading the whole buffer. + ****************************************************************************/ + +void ltt_tracefile_seek_position(LttTracefile *t, const LttEventPosition *ep) +{ + //if we are at the right place, just return + if(likely(t->which_block == ep->block_num && t->which_event == ep->event_num)) + return; + + if(likely(t->which_block == ep->block_num)) updateTracefile(t); + else readBlock(t,ep->block_num); + //event offset is available + if(likely(ep->old_position)){ + int err; + + t->which_event = ep->event_num; + t->cur_event_pos = t->buffer + ep->event_offset; + t->prev_event_time = ep->event_time; + t->current_event_time = ep->event_time; + t->cur_heart_beat_number = ep->heart_beat_number; + t->cur_cycle_count = ep->event_cycle_count; + + /* This is a workaround for fast position seek */ + t->last_event_pos = ep->last_event_pos; + t->prev_block_end_time = ep->prev_block_end_time; + t->prev_event_time = ep->prev_event_time; + t->pre_cycle_count = ep->pre_cycle_count; + t->count = ep->count; + t->overflow_nsec = ep->overflow_nsec; + t->last_heartbeat = ep->last_heartbeat; + /* end of workaround */ + + //update the fields of the current event and go to the next event + err = skipEvent(t); + if(unlikely(err == ERANGE)) g_error("event id is out of range\n"); + + return; + } + + //only block number and event index are available + //MD: warning : this is slow! + g_warning("using slow O(n) tracefile seek position"); + + LttEvent event; + while(likely(t->which_event < ep->event_num)) ltt_tracefile_read(t, &event); + + return; +} + +/***************************************************************************** + *Function name + * ltt_tracefile_read : read the current event, set the pointer to the next + *Input params + * t : tracefile + *Return value + * LttEvent * : an event to be processed + ****************************************************************************/ + +LttEvent *ltt_tracefile_read(LttTracefile *t, LttEvent *event) +{ + int err; + + if(unlikely(t->cur_event_pos == t->buffer + t->block_size)){ + if(unlikely(t->which_block == t->block_number)){ + return NULL; + } + err = readBlock(t, t->which_block + 1); + if(unlikely(err))g_error("Can not read tracefile"); + } + + event->event_id = ltt_get_uint16(t->trace->reverse_byte_order, t->cur_event_pos); + if(unlikely(event->event_id == TRACE_TIME_HEARTBEAT)) + t->cur_heart_beat_number++; + + t->prev_event_time = t->current_event_time; + // t->current_event_time = getEventTime(t); + + event->time_delta = ltt_get_uint32(t->trace->reverse_byte_order, t->cur_event_pos + EVENT_ID_SIZE); + event->event_time = t->current_event_time; + event->event_cycle_count = t->cur_cycle_count; + + event->tracefile = t; + event->data = t->cur_event_pos + EVENT_HEADER_SIZE; + event->which_block = t->which_block; + event->which_event = t->which_event; + + /* This is a workaround for fast position seek */ + event->last_event_pos = t->last_event_pos; + event->prev_block_end_time = t->prev_block_end_time; + event->prev_event_time = t->prev_event_time; + event->pre_cycle_count = t->pre_cycle_count; + event->count = t->count; + event->overflow_nsec = t->overflow_nsec; + event->last_heartbeat = t->last_heartbeat; + + /* end of workaround */ + + + + //update the fields of the current event and go to the next event + err = skipEvent(t); + if(unlikely(err == ERANGE)) g_error("event id is out of range\n"); + + return event; +} + +/**************************************************************************** + *Function name + * readFile : wrap function to read from a file + *Input Params + * fd : file descriptor + * buf : buf to contain the content + * size : number of bytes to be read + * mesg : message to be printed if some thing goes wrong + *return value + * 0 : success + * EIO : can not read from the file + ****************************************************************************/ + +int readFile(int fd, void * buf, size_t size, char * mesg) +{ + ssize_t nbBytes = read(fd, buf, size); + + if((size_t)nbBytes != size) { + if(nbBytes < 0) { + perror("Error in readFile : "); + } else { + g_warning("%s",mesg); + } + return EIO; + } + return 0; +} + + +/**************************************************************************** + *Function name + * readBlock : read a block from the file + *Input Params + * lttdes : ltt trace file + * whichBlock : the block which will be read + *return value + * 0 : success + * EINVAL : lseek fail + * EIO : can not read from the file + ****************************************************************************/ + +int readBlock(LttTracefile * tf, int whichBlock) +{ + off_t nbBytes; + guint32 lostSize; + + /* same block already opened requested */ + if((guint)whichBlock == tf->which_block) return 0; + + if(likely(whichBlock - tf->which_block == 1 && tf->which_block != 0)){ + tf->prev_block_end_time = ltt_get_time(tf->trace->reverse_byte_order, + &tf->a_block_end->time); + tf->prev_event_time = ltt_get_time(tf->trace->reverse_byte_order, + &tf->a_block_end->time); + }else{ + tf->prev_block_end_time.tv_sec = 0; + tf->prev_block_end_time.tv_nsec = 0; + tf->prev_event_time.tv_sec = 0; + tf->prev_event_time.tv_nsec = 0; + } + + nbBytes=lseek(tf->fd,(off_t)((whichBlock-1)*tf->block_size), SEEK_SET); + if(unlikely(nbBytes == -1)) return EINVAL; + + if(unlikely(readFile(tf->fd,tf->buffer,tf->block_size,"Unable to read a block"))) + return EIO; + + tf->a_block_start=(BlockStart *) (tf->buffer + EVENT_HEADER_SIZE); + lostSize = *(guint32 *)(tf->buffer + tf->block_size - sizeof(guint32)); + tf->a_block_end=(BlockEnd *)(tf->buffer + tf->block_size + - sizeof(guint32) - lostSize - sizeof(BlockEnd)); + tf->last_event_pos = tf->buffer + tf->block_size - + sizeof(guint32) - lostSize + - sizeof(BlockEnd) - EVENT_HEADER_SIZE; + + tf->which_block = whichBlock; + tf->which_event = 1; + tf->cur_event_pos = tf->buffer;//the beginning of the block, block start ev + tf->cur_heart_beat_number = 0; + tf->last_heartbeat = NULL; + + /* read the whole block to precalculate total of cycles in it */ + tf->count = 0; + tf->pre_cycle_count = 0; + tf->cur_cycle_count = ltt_get_uint32(tf->trace->reverse_byte_order, tf->cur_event_pos + EVENT_ID_SIZE); + + getCyclePerNsec(tf); + + tf->overflow_nsec = + (-((double) + (ltt_get_uint64(tf->trace->reverse_byte_order, + &tf->a_block_start->cycle_count)&0xFFFFFFFF)) + * tf->nsec_per_cycle); + + tf->current_event_time = getEventTime(tf); + + return 0; +} + +/***************************************************************************** + *Function name + * updateTracefile : reinitialize the info of the block which is already + * in the buffer + *Input params + * tf : tracefile + ****************************************************************************/ + +void updateTracefile(LttTracefile * tf) +{ + tf->which_event = 1; + tf->cur_event_pos = tf->buffer; + tf->current_event_time = getEventTime(tf); + tf->cur_heart_beat_number = 0; + + tf->prev_event_time.tv_sec = 0; + tf->prev_event_time.tv_nsec = 0; + tf->count = 0; + + tf->overflow_nsec = + (-((double)ltt_get_uint64(tf->trace->reverse_byte_order, + &tf->a_block_start->cycle_count)) + * tf->nsec_per_cycle); + +} + +/***************************************************************************** + *Function name + * skipEvent : go to the next event, update the fields of the current event + *Input params + * t : tracefile + *return value + * 0 : success + * ERANGE : event id is out of range + ****************************************************************************/ + +int skipEvent(LttTracefile * t) +{ + int evId; + void * evData; + LttEventType * evT; + LttField * rootFld; + + evId = ltt_get_uint16(t->trace->reverse_byte_order, t->cur_event_pos); + evData = t->cur_event_pos + EVENT_HEADER_SIZE; + + evT = ltt_trace_eventtype_get(t->trace,(unsigned)evId); + + if(likely(evT)) rootFld = evT->root_field; + else return ERANGE; + + if(likely(rootFld)){ + //event has string/sequence or the last event is not the same event + if(likely((evT->latest_block!=t->which_block || evT->latest_event!=t->which_event) + && rootFld->field_fixed == 0)){ + setFieldsOffset(t, evT, evData, t->trace); + } + t->cur_event_pos += EVENT_HEADER_SIZE + rootFld->field_size; + }else t->cur_event_pos += EVENT_HEADER_SIZE; + + evT->latest_block = t->which_block; + evT->latest_event = t->which_event; + + //the next event is in the next block + if(unlikely(evId == TRACE_BLOCK_END)){ + t->cur_event_pos = t->buffer + t->block_size; + }else{ + t->cur_cycle_count = ltt_get_uint32(t->trace->reverse_byte_order, + t->cur_event_pos + EVENT_ID_SIZE); + t->which_event++; + t->current_event_time = getEventTime(t); + } + + return 0; +} + + +/***************************************************************************** + *Function name + * getCyclePerNsec : calculate cycles per nsec for current block + * MD: should have tracefile_read the whole block, so we know the + * total of cycles in it before being called. + *Input Params + * t : tracefile + ****************************************************************************/ + +void getCyclePerNsec(LttTracefile * t) +{ + LttTime lBufTotalTime; /* Total time for this buffer */ + double lBufTotalNSec; /* Total time for this buffer in nsecs */ + LttCycleCount lBufTotalCycle;/* Total cycles for this buffer */ + + /* Calculate the total time for this buffer */ + lBufTotalTime = ltt_time_sub( + ltt_get_time(t->trace->reverse_byte_order, &t->a_block_end->time), + ltt_get_time(t->trace->reverse_byte_order, &t->a_block_start->time)); + + /* Calculate the total cycles for this bufffer */ + lBufTotalCycle = ltt_get_uint64(t->trace->reverse_byte_order, + &t->a_block_end->cycle_count); + lBufTotalCycle -= ltt_get_uint64(t->trace->reverse_byte_order, + &t->a_block_start->cycle_count); + + /* Convert the total time to double */ + lBufTotalNSec = ltt_time_to_double(lBufTotalTime); + + t->nsec_per_cycle = (double)lBufTotalNSec / (double)lBufTotalCycle; + + /* Pre-multiply one overflow (2^32 cycles) by nsec_per_cycle */ + t->one_overflow_nsec = t->nsec_per_cycle * (double)0x100000000ULL; + +} + +/**************************************************************************** + *Function name + * getEventTime : obtain the time of an event + * NOTE : this function _really_ is on critical path. + *Input params + * tf : tracefile + *Return value + * LttTime : the time of the event + ****************************************************************************/ + +static inline LttTime getEventTime(LttTracefile * tf) +{ + LttTime time; + LttCycleCount cycle_count; // cycle count for the current event + //LttCycleCount lEventTotalCycle; // Total cycles from start for event + gint64 lEventNSec; // Total nsecs from start for event + LttTime lTimeOffset; // Time offset in struct LttTime + guint16 evId; + + evId = ltt_get_uint16(tf->trace->reverse_byte_order, + tf->cur_event_pos); + + cycle_count = ltt_get_uint32(tf->trace->reverse_byte_order, + tf->cur_event_pos + EVENT_ID_SIZE); + + gboolean comp_count = cycle_count < tf->pre_cycle_count; + + tf->pre_cycle_count = cycle_count; + + if(unlikely(comp_count)) { + /* Overflow */ + tf->overflow_nsec += tf->one_overflow_nsec; + tf->count++; //increment overflow count + } + + if(unlikely(evId == TRACE_BLOCK_START)) { + lEventNSec = 0; + } else if(unlikely(evId == TRACE_BLOCK_END)) { + lEventNSec = ((double) + (ltt_get_uint64(tf->trace->reverse_byte_order, + &tf->a_block_end->cycle_count) + - ltt_get_uint64(tf->trace->reverse_byte_order, + &tf->a_block_start->cycle_count)) + * tf->nsec_per_cycle); + } +#if 0 + /* If you want to make heart beat a special case and use their own 64 bits + * TSC, activate this. + */ + else if(unlikely(evId == TRACE_TIME_HEARTBEAT)) { + + tf->last_heartbeat = (TimeHeartbeat*)(tf->cur_event_pos+EVENT_HEADER_SIZE); + lEventNSec = ((double)(tf->last_heartbeat->cycle_count + - tf->a_block_start->cycle_count) + * tf->nsec_per_cycle); + } +#endif //0 + else { + lEventNSec = (gint64)((double)cycle_count * tf->nsec_per_cycle) + +tf->overflow_nsec; + } + + lTimeOffset = ltt_time_from_uint64(lEventNSec); + + time = ltt_time_add(ltt_get_time(tf->trace->reverse_byte_order, + &tf->a_block_start->time), lTimeOffset); + + return time; +} + +/***************************************************************************** + *Function name + * setFieldsOffset : set offset of the fields + *Input params + * tracefile : opened trace file + * evT : the event type + * evD : event data, it may be NULL + ****************************************************************************/ + +void setFieldsOffset(LttTracefile *tf,LttEventType *evT,void *evD,LttTrace* t) +{ + LttField * rootFld = evT->root_field; + // rootFld->base_address = evD; + + if(likely(rootFld)) + rootFld->field_size = getFieldtypeSize(tf, evT, 0,0,rootFld, evD,t); +} + +/***************************************************************************** + *Function name + * getFieldtypeSize: get the size of the field type (primitive type) + *Input params + * tracefile : opened trace file + * evT : event type + * offsetRoot : offset from the root + * offsetParent : offset from the parrent + * fld : field + * evD : event data, it may be NULL + *Return value + * int : size of the field + ****************************************************************************/ + +static inline gint getFieldtypeSize(LttTracefile * t, + LttEventType * evT, gint offsetRoot, + gint offsetParent, LttField * fld, void *evD, LttTrace *trace) +{ + gint size, size1, element_number, i, offset1, offset2; + LttType * type = fld->field_type; + + if(unlikely(t && evT->latest_block==t->which_block && + evT->latest_event==t->which_event)){ + size = fld->field_size; + goto end_getFieldtypeSize; + } else { + /* This likely has been tested with gcov : half of them.. */ + if(unlikely(fld->field_fixed == 1)){ + /* tested : none */ + if(unlikely(fld == evT->root_field)) { + size = fld->field_size; + goto end_getFieldtypeSize; + } + } + + /* From gcov profiling : half string, half struct, can we gain something + * from that ? (Mathieu) */ + switch(type->type_class) { + case LTT_ARRAY: + element_number = (int) type->element_number; + if(fld->field_fixed == -1){ + size = getFieldtypeSize(t, evT, offsetRoot, + 0,fld->child[0], NULL, trace); + if(size == 0){ //has string or sequence + fld->field_fixed = 0; + }else{ + fld->field_fixed = 1; + size *= element_number; + } + }else if(fld->field_fixed == 0){// has string or sequence + size = 0; + for(i=0;ichild[0], evD+size, trace); + } + }else size = fld->field_size; + if(unlikely(!evD)){ + fld->fixed_root = (offsetRoot==-1) ? 0 : 1; + fld->fixed_parent = (offsetParent==-1) ? 0 : 1; + } + + break; + + case LTT_SEQUENCE: + size1 = (int) ltt_type_size(trace, type); + if(fld->field_fixed == -1){ + fld->sequ_number_size = size1; + fld->field_fixed = 0; + size = getFieldtypeSize(t, evT, offsetRoot, + 0,fld->child[0], NULL, trace); + fld->element_size = size; + }else{//0: sequence + element_number = getIntNumber(t->trace->reverse_byte_order,size1,evD); + type->element_number = element_number; + if(fld->element_size > 0){ + size = element_number * fld->element_size; + }else{//sequence has string or sequence + size = 0; + for(i=0;ichild[0], evD+size+size1, trace); + } + } + size += size1; + } + if(unlikely(!evD)){ + fld->fixed_root = (offsetRoot==-1) ? 0 : 1; + fld->fixed_parent = (offsetParent==-1) ? 0 : 1; + } + + break; + + case LTT_STRING: + size = 0; + if(fld->field_fixed == -1){ + fld->field_fixed = 0; + }else{//0: string + /* Hope my implementation is faster than strlen (Mathieu) */ + char *ptr=(char*)evD; + size = 1; + /* from gcov : many many strings are empty, make it the common case.*/ + while(unlikely(*ptr != '\0')) { size++; ptr++; } + //size = ptr - (char*)evD + 1; //include end : '\0' + } + fld->fixed_root = (offsetRoot==-1) ? 0 : 1; + fld->fixed_parent = (offsetParent==-1) ? 0 : 1; + + break; + + case LTT_STRUCT: + element_number = (int) type->element_number; + size = 0; + /* tested with gcov */ + if(unlikely(fld->field_fixed == -1)){ + offset1 = offsetRoot; + offset2 = 0; + for(i=0;ichild[i], NULL, trace); + if(likely(size1 > 0 && size >= 0)){ + size += size1; + if(likely(offset1 >= 0)) offset1 += size1; + offset2 += size1; + }else{ + size = -1; + offset1 = -1; + offset2 = -1; + } + } + if(unlikely(size == -1)){ + fld->field_fixed = 0; + size = 0; + }else fld->field_fixed = 1; + }else if(likely(fld->field_fixed == 0)){ + offset1 = offsetRoot; + offset2 = 0; + for(i=0;unlikely(ichild[i],evD+offset2, trace); + offset1 += size; + offset2 += size; + } + size = offset2; + }else size = fld->field_size; + fld->fixed_root = (offsetRoot==-1) ? 0 : 1; + fld->fixed_parent = (offsetParent==-1) ? 0 : 1; + break; + + default: + if(unlikely(fld->field_fixed == -1)){ + size = (int) ltt_type_size(trace, type); + fld->field_fixed = 1; + }else size = fld->field_size; + if(unlikely(!evD)){ + fld->fixed_root = (offsetRoot==-1) ? 0 : 1; + fld->fixed_parent = (offsetParent==-1) ? 0 : 1; + } + break; + } + } + + fld->offset_root = offsetRoot; + fld->offset_parent = offsetParent; + fld->field_size = size; + +end_getFieldtypeSize: + + return size; +} + + +/***************************************************************************** + *Function name + * getIntNumber : get an integer number + *Input params + * size : the size of the integer + * evD : the event data + *Return value + * gint64 : a 64 bits integer + ****************************************************************************/ + +gint64 getIntNumber(gboolean reverse_byte_order, int size, void *evD) +{ + gint64 i; + + switch(size) { + case 1: i = *((gint8*)evD); break; + case 2: i = ltt_get_int16(reverse_byte_order, evD); break; + case 4: i = ltt_get_int32(reverse_byte_order, evD); break; + case 8: i = ltt_get_int64(reverse_byte_order, evD); break; + default: i = ltt_get_int64(reverse_byte_order, evD); + g_critical("getIntNumber : integer size %d unknown", size); + break; + } + + return i; +} +#if 0 +/***************************************************************************** + *Function name + * getDataEndianType : get the data type size and endian type of the local + * machine + *Input params + * size : size of data type + * endian : endian type, little or big + ****************************************************************************/ + +void getDataEndianType(LttArchSize * size, LttArchEndian * endian) +{ + int i = 1; + char c = (char) i; + int sizeInt=sizeof(int), sizeLong=sizeof(long), sizePointer=sizeof(void *); + + if(c == 1) *endian = LTT_LITTLE_ENDIAN; + else *endian = LTT_BIG_ENDIAN; + + if(sizeInt == 2 && sizeLong == 4 && sizePointer == 4) + *size = LTT_LP32; + else if(sizeInt == 4 && sizeLong == 4 && sizePointer == 4) + *size = LTT_ILP32; + else if(sizeInt == 4 && sizeLong == 8 && sizePointer == 8) + *size = LTT_LP64; + else if(sizeInt == 8 && sizeLong == 8 && sizePointer == 8) + *size = LTT_ILP64; + else *size = LTT_UNKNOWN; +} +#endif //0 +/* get the node name of the system */ + +char * ltt_trace_system_description_node_name (LttSystemDescription * s) +{ + return s->node_name; +} + + +/* get the domain name of the system */ + +char * ltt_trace_system_description_domain_name (LttSystemDescription * s) +{ + return s->domain_name; +} + + +/* get the description of the system */ + +char * ltt_trace_system_description_description (LttSystemDescription * s) +{ + return s->description; +} + + +/* get the start time of the trace */ + +LttTime ltt_trace_system_description_trace_start_time(LttSystemDescription *s) +{ + return s->trace_start; +} + + +LttTracefile *ltt_tracefile_new() +{ + return g_new(LttTracefile, 1); +} + +void ltt_tracefile_destroy(LttTracefile *tf) +{ + g_free(tf); +} + +void ltt_tracefile_copy(LttTracefile *dest, const LttTracefile *src) +{ + *dest = *src; +} + diff --git a/ltt/branches/poly/ltt-newlib/type.c b/ltt/branches/poly/ltt-oldlib/type.c similarity index 86% rename from ltt/branches/poly/ltt-newlib/type.c rename to ltt/branches/poly/ltt-oldlib/type.c index 44f218f1..7f134eda 100644 --- a/ltt/branches/poly/ltt-newlib/type.c +++ b/ltt/branches/poly/ltt-oldlib/type.c @@ -49,10 +49,10 @@ static unsigned floatSizes[] = { *Input params * et : an event type *Return value - * GQuark : the name of the event type + * char * : the name of the event type ****************************************************************************/ -GQuark ltt_eventtype_name(LttEventType *et) +gchar *ltt_eventtype_name(LttEventType *et) { return et->name; } @@ -85,6 +85,20 @@ LttFacility *ltt_eventtype_facility(LttEventType *et) return et->facility; } +/***************************************************************************** + *Function name + * ltt_eventtype_relative_id : get the relative id of the event type + *Input params + * et : an event type + *Return value + * unsigned : the relative id + ****************************************************************************/ + +unsigned ltt_eventtype_relative_id(LttEventType *et) +{ + return et->index; +} + /***************************************************************************** *Function name * ltt_eventtype_id : get the id of the event type @@ -94,9 +108,9 @@ LttFacility *ltt_eventtype_facility(LttEventType *et) * unsigned : the id ****************************************************************************/ -guint8 ltt_eventtype_id(LttEventType *et) +unsigned ltt_eventtype_id(LttEventType *et) { - return et->index; + return et->facility->base_id + et->index; } /***************************************************************************** @@ -137,7 +151,7 @@ LttField *ltt_eventtype_field(LttEventType *et) * char * : the name of the type ****************************************************************************/ -GQuark ltt_type_name(LttType *t) +gchar *ltt_type_name(LttType *t) { return t->element_name; } @@ -159,58 +173,47 @@ LttTypeEnum ltt_type_class(LttType *t) /***************************************************************************** *Function name * ltt_type_size : obtain the type size. The size is the number of bytes - * for primitive types (INT, UINT, FLOAT, ENUM) - * or the size for the unsigned integer length count for - * sequences + * for primitive types (INT, UINT, FLOAT, ENUM), or the + * size for the unsigned integer length count for sequences *Input params * tf : trace file * t : a type *Return value - * : the type size + * unsigned : the type size * returns 0 if erroneous, and show a critical warning message. ****************************************************************************/ -size_t ltt_type_size(LttTrace * trace, LttType *t) +unsigned ltt_type_size(LttTrace * trace, LttType *t) { - size_t size; - - switch(t->type_class) { - - case LTT_INT: - case LTT_UINT: - case LTT_SEQUENCE: - case LTT_ENUM: + unsigned size; + if(unlikely(t->type_class==LTT_STRUCT || t->type_class==LTT_ARRAY || + t->type_class==LTT_STRING || t->type_class==LTT_UNION)) { + size = 0; + } else { + if(t->type_class == LTT_FLOAT){ + size = floatSizes[t->size]; + }else{ if(likely(t->size < INT_SIZES_NUMBER)) size = intSizes[t->size]; - else - goto error; - break; - case LTT_FLOAT: - if(likely(t->size < FLOAT_SIZES_NUMBER)) - size = floatSizes[t->size]; - else - goto error; - break; - case LTT_POINTER: - case LTT_LONG: - case LTT_ULONG: - case LTT_SIZE_T: - case LTT_SSIZE_T: - case LTT_OFF_T: - case LTT_STRING: - case LTT_ARRAY: - case LTT_STRUCT: - case LTT_UNION: - goto error; - break; + else{ + LttArchSize archsize = trace->system_description->size; + if(archsize == LTT_LP32){ + if(t->size == 5) size = intSizes[SIZE_INT16]; + else size = intSizes[SIZE_INT32]; + } + else if(archsize == LTT_ILP32 || archsize == LTT_LP64){ + if(t->size == 5) size = intSizes[SIZE_INT32]; + else{ + if(archsize == LTT_ILP32) size = intSizes[SIZE_INT32]; + else size = intSizes[SIZE_INT64]; + } + } + else if(archsize == LTT_ILP64) size = intSizes[SIZE_INT64]; + } + } } return size; - - -error: - g_warning("no size known for the type"); - return 0; } /***************************************************************************** diff --git a/ltt/branches/poly/ltt-newlib/type.h b/ltt/branches/poly/ltt-oldlib/type.h similarity index 93% rename from ltt/branches/poly/ltt-newlib/type.h rename to ltt/branches/poly/ltt-oldlib/type.h index fca7e42d..01cbbb38 100644 --- a/ltt/branches/poly/ltt-newlib/type.h +++ b/ltt/branches/poly/ltt-oldlib/type.h @@ -31,7 +31,7 @@ /* Obtain the name, description, facility, facility relative id, global id, type and root field for an eventtype */ -GQuark ltt_eventtype_name(LttEventType *et); +gchar *ltt_eventtype_name(LttEventType *et); gchar *ltt_eventtype_description(LttEventType *et); @@ -50,7 +50,7 @@ LttField *ltt_eventtype_field(LttEventType *et); primitive types (INT, UINT, FLOAT, ENUM), or the size for the unsigned integer length count for sequences. */ -GQuark ltt_type_name(LttType *t); +gchar *ltt_type_name(LttType *t); LttTypeEnum ltt_type_class(LttType *t); @@ -74,13 +74,13 @@ unsigned ltt_type_member_number(LttType *t); /* The type of a data member in a structure. */ -LttType *ltt_type_member_type(LttType *t, unsigned i, GQuark *name); +LttType *ltt_type_member_type(LttType *t, unsigned i, char ** name); /* For enumerations, obtain the symbolic string associated with a value (0 to n - 1 for an enumeration of n elements). */ -GQuark ltt_enum_string_get(LttType *t, unsigned i); +gchar *ltt_enum_string_get(LttType *t, unsigned i); /* The fields form a tree representing a depth first search of the diff --git a/ltt/branches/poly/ltt/event.c b/ltt/branches/poly/ltt/event.c index fe299b5d..52344487 100644 --- a/ltt/branches/poly/ltt/event.c +++ b/ltt/branches/poly/ltt/event.c @@ -35,7 +35,6 @@ #include #include - LttEvent *ltt_event_new() { return g_new(LttEvent, 1); @@ -188,7 +187,7 @@ int ltt_event_refresh_fields(int offsetRoot,int offsetParent, * unsigned : event type id ****************************************************************************/ -unsigned ltt_event_eventtype_id(LttEvent *e) +unsigned ltt_event_eventtype_id(const LttEvent *e) { return (unsigned) e->event_id; } @@ -202,13 +201,27 @@ unsigned ltt_event_eventtype_id(LttEvent *e) * LttFacility * : the facility of the event ****************************************************************************/ -LttFacility *ltt_event_facility(LttEvent *e) +LttFacility *ltt_event_facility(const LttEvent *e) { LttTrace * trace = e->tracefile->trace; unsigned id = e->event_id; return ltt_trace_facility_by_id(trace,id); } +/***************************************************************************** + *Function name + * ltt_event_facility_id : get the facility id of the event + *Input params + * e : an instance of an event type + *Return value + * unsigned : the facility of the event + ****************************************************************************/ + +unsigned ltt_event_facility_id(const LttEvent *e) +{ + return e->facility_id; +} + /***************************************************************************** *Function name * ltt_event_eventtype : get the event type of the event @@ -218,7 +231,7 @@ LttFacility *ltt_event_facility(LttEvent *e) * LttEventType * : the event type of the event ****************************************************************************/ -LttEventType *ltt_event_eventtype(LttEvent *e) +LttEventType *ltt_event_eventtype(const LttEvent *e) { LttFacility* facility = ltt_event_facility(e); if(!facility) return NULL; @@ -257,7 +270,7 @@ LttField *ltt_event_field(LttEvent *e) * LttTime : the time of the event ****************************************************************************/ -LttTime ltt_event_time(LttEvent *e) +LttTime ltt_event_time(const LttEvent *e) { return e->event_time; } @@ -271,11 +284,34 @@ LttTime ltt_event_time(LttEvent *e) * LttCycleCount : the cycle count of the event ****************************************************************************/ -LttCycleCount ltt_event_cycle_count(LttEvent *e) +LttCycleCount ltt_event_cycle_count(const LttEvent *e) { return e->tsc; } + + +/***************************************************************************** + *Function name + * ltt_event_position_get : get the event position data + *Input params + * e : an instance of an event type + * ep : a pointer to event's position structure + * tf : tracefile pointer + * block : current block + * offset : current offset + * tsc : current tsc + ****************************************************************************/ +void ltt_event_position_get(LttEventPosition *ep, LttTracefile **tf, + guint *block, guint *offset, guint64 *tsc) +{ + *tf = ep->tracefile; + *block = ep->block; + *offset = ep->offset; + *tsc = ep->tsc; +} + + /***************************************************************************** *Function name * ltt_event_position : get the event's position @@ -403,7 +439,7 @@ guint64 ltt_event_field_element_number(LttEvent *e, LttField *f) if(f->field_type->type_class == LTT_ARRAY) return f->field_type->element_number; - return get_unsigned(LTT_GET_BO(e->tracefile), f->sequ_number_size, + return ltt_get_uint(LTT_GET_BO(e->tracefile), f->sequ_number_size, e + f->offset_root); } @@ -603,3 +639,135 @@ char *ltt_event_get_string(LttEvent *e, LttField *f) return (gchar*)g_strdup((gchar*)(e->data + f->offset_root)); } + + +/***************************************************************************** + *Function name + * get_field_type_size : set the fixed and dynamic sizes of the field type + * from the data read. + *Input params + * tf : tracefile + * event_type : event type + * offset_root : offset from the root + * offset_parent : offset from the parent + * field : field + * data : a pointer to the event data. + *Returns the field type size. + ****************************************************************************/ +size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type, + off_t offset_root, off_t offset_parent, + LttField *field, void *data) +{ + size_t size = 0; + guint i; + LttType *type; + + g_assert(field->fixed_root != FIELD_UNKNOWN); + g_assert(field->fixed_parent != FIELD_UNKNOWN); + g_assert(field->fixed_size != FIELD_UNKNOWN); + + field->offset_root = offset_root; + field->offset_parent = offset_parent; + + type = field->field_type; + + switch(type->type_class) { + case LTT_INT: + case LTT_UINT: + case LTT_FLOAT: + case LTT_ENUM: + case LTT_POINTER: + case LTT_LONG: + case LTT_ULONG: + case LTT_SIZE_T: + case LTT_SSIZE_T: + case LTT_OFF_T: + g_assert(field->fixed_size == FIELD_FIXED); + size = field->field_size; + break; + case LTT_SEQUENCE: + { + gint seqnum = ltt_get_uint(LTT_GET_BO(tf), + field->sequ_number_size, + data + offset_root); + + if(field->child[0]->fixed_size == FIELD_FIXED) { + size = field->sequ_number_size + + (seqnum * get_field_type_size(tf, event_type, + offset_root, offset_parent, + field->child[0], data)); + } else { + size += field->sequ_number_size; + for(i=0;ichild[0], data); + offset_root += child_size; + offset_parent += child_size; + size += child_size; + } + } + field->field_size = size; + } + break; + case LTT_STRING: + size = strlen((char*)(data+offset_root)) + 1;// length + \0 + field->field_size = size; + break; + case LTT_ARRAY: + if(field->fixed_size == FIELD_FIXED) + size = field->field_size; + else { + for(i=0;ifield_type->element_number;i++) { + size_t child_size; + child_size = get_field_type_size(tf, event_type, + offset_root, offset_parent, + field->child[0], data); + offset_root += child_size; + offset_parent += child_size; + size += child_size; + } + field->field_size = size; + } + break; + case LTT_STRUCT: + if(field->fixed_size == FIELD_FIXED) + size = field->field_size; + else { + size_t current_root_offset = offset_root; + size_t current_offset = 0; + size_t child_size = 0; + for(i=0;ielement_number;i++) { + child_size = get_field_type_size(tf, + event_type, current_root_offset, current_offset, + field->child[i], data); + current_offset += child_size; + current_root_offset += child_size; + + } + size = current_offset; + field->field_size = size; + } + break; + case LTT_UNION: + if(field->fixed_size == FIELD_FIXED) + size = field->field_size; + else { + size_t current_root_offset = field->offset_root; + size_t current_offset = 0; + for(i=0;ielement_number;i++) { + size = get_field_type_size(tf, event_type, + current_root_offset, current_offset, + field->child[i], data); + size = max(size, field->child[i]->field_size); + } + field->field_size = size; + } + break; + } + + return size; +} + + diff --git a/ltt/branches/poly/ltt/event.h b/ltt/branches/poly/ltt/event.h index fc50fee9..1c8d40fb 100644 --- a/ltt/branches/poly/ltt/event.h +++ b/ltt/branches/poly/ltt/event.h @@ -21,6 +21,7 @@ #include #include +#include LttEvent *ltt_event_new(); @@ -34,14 +35,15 @@ void ltt_event_destroy(LttEvent *event); /* Obtain the trace unique integer id associated with the type of this event */ -unsigned ltt_event_eventtype_id(LttEvent *e); +unsigned ltt_event_eventtype_id(const LttEvent *e); +unsigned ltt_event_facility_id(const LttEvent *e); /* Facility and type for the event */ -LttFacility *ltt_event_facility(LttEvent *e); +LttFacility *ltt_event_facility(const LttEvent *e); -LttEventType *ltt_event_eventtype(LttEvent *e); +LttEventType *ltt_event_eventtype(const LttEvent *e); /* Root field for the event */ @@ -51,9 +53,9 @@ LttField *ltt_event_field(LttEvent *e); /* Time and cycle count for the event */ -LttTime ltt_event_time(LttEvent *e); +LttTime ltt_event_time(const LttEvent *e); -LttCycleCount ltt_event_cycle_count(LttEvent *e); +LttCycleCount ltt_event_cycle_count(const LttEvent *e); /* Obtain the position of the event within the tracefile. This @@ -67,18 +69,12 @@ void ltt_event_position(LttEvent *e, LttEventPosition *ep); LttEventPosition * ltt_event_position_new(); -void ltt_event_position_get(LttEventPosition *ep, - unsigned *block_number, unsigned *index_in_block, LttTracefile ** tf); - -void ltt_event_position_set(LttEventPosition *ep, - unsigned block_number, unsigned index_in_block); +void ltt_event_position_get(LttEventPosition *ep, LttTracefile **tf, + guint *block, guint *offset, guint64 *tsc); gint ltt_event_position_compare(const LttEventPosition *ep1, const LttEventPosition *ep2); -gint ltt_event_event_position_compare(const LttEvent *event, - const LttEventPosition *ep); - void ltt_event_position_copy(LttEventPosition *dest, const LttEventPosition *src); @@ -133,4 +129,11 @@ double ltt_event_get_double(LttEvent *e, LttField *f); gchar *ltt_event_get_string(LttEvent *e, LttField *f); +size_t get_field_type_size(LttTracefile *tf, + LttEventType *event_type, + off_t offset_root, off_t offset_parent, + LttField *field, void *data); + + + #endif // EVENT_H diff --git a/ltt/branches/poly/ltt/ltt-private.h b/ltt/branches/poly/ltt/ltt-private.h index 5fa28863..8c0308c4 100644 --- a/ltt/branches/poly/ltt/ltt-private.h +++ b/ltt/branches/poly/ltt/ltt-private.h @@ -23,6 +23,12 @@ #include #include + +#ifndef max +#define max(a,b) ((a)>(b)?(a):(b)) +#endif + + #define LTT_MAGIC_NUMBER 0x00D6B7ED #define LTT_REV_MAGIC_NUMBER 0xEDB7D600 @@ -181,7 +187,7 @@ struct _LttEvent{ /* Begin of LttEventPosition fields */ LttTracefile *tracefile; unsigned int block; - void *offset; + unsigned int offset; /* Timekeeping */ uint64_t tsc; /* Current timestamp counter */ @@ -208,7 +214,7 @@ struct _LttEvent{ struct _LttEventPosition{ LttTracefile *tracefile; unsigned int block; - void *offset; + unsigned int offset; /* Timekeeping */ uint64_t tsc; /* Current timestamp counter */ diff --git a/ltt/branches/poly/ltt/trace.h b/ltt/branches/poly/ltt/trace.h index 3b113167..e91b4954 100644 --- a/ltt/branches/poly/ltt/trace.h +++ b/ltt/branches/poly/ltt/trace.h @@ -21,7 +21,6 @@ #include - extern GQuark LTT_FACILITY_NAME_HEARTBEAT, LTT_EVENT_NAME_HEARTBEAT; @@ -106,6 +105,9 @@ int ltt_tracefile_read_seek(LttTracefile *t); int ltt_tracefile_read_update_event(LttTracefile *t); int ltt_tracefile_read_op(LttTracefile *t); +/* Get the current event of the tracefile : valid until the next read */ +LttEvent *ltt_tracefile_get_event(LttTracefile *tf); + /* open tracefile */ gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf); diff --git a/ltt/branches/poly/ltt/tracefile.c b/ltt/branches/poly/ltt/tracefile.c index 1b29605f..333d9cb5 100644 --- a/ltt/branches/poly/ltt/tracefile.c +++ b/ltt/branches/poly/ltt/tracefile.c @@ -79,7 +79,7 @@ static inline LttTime getEventTime(LttTracefile * tf); /* set the offset of the fields belonging to the event, need the information of the archecture */ void set_fields_offsets(LttTracefile *tf, LttEventType *event_type); -size_t get_fields_offsets(LttTracefile *tf, LttEventType *event_type, void *data); +//size_t get_fields_offsets(LttTracefile *tf, LttEventType *event_type, void *data); /* get the size of the field type according to * The facility size information. */ @@ -89,13 +89,6 @@ static inline void preset_field_type_size(LttTracefile *tf, enum field_status *fixed_root, enum field_status *fixed_parent, LttField *field); - -static inline size_t get_field_type_size(LttTracefile *tf, - LttEventType *event_type, - off_t offset_root, off_t offset_parent, - LttField *field, void *data); - - /* map a fixed size or a block information from the file (fd) */ static gint map_block(LttTracefile * tf, guint block_num); @@ -105,6 +98,8 @@ static double calc_nsecs_per_cycle(LttTracefile * t); /* go to the next event */ static int ltt_seek_next_event(LttTracefile *tf); +void ltt_update_event_size(LttTracefile *tf); + #if 0 /* Functions to parse system.xml file (using glib xml parser) */ static void parser_start_element (GMarkupParseContext __UNUSED__ *context, @@ -252,7 +247,7 @@ gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf) tf->block_size = header->buf_size; tf->num_blocks = tf->file_size / tf->block_size; - vfree(tf->buffer.head); + munmap(tf->buffer.head, sizeof(struct ltt_block_start_header)); tf->buffer.head = NULL; //read the first block @@ -829,7 +824,7 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) fac->id = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->id); fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->pointer_size); - fac->size_t_size = ltt_get_uin32(LTT_GET_BO(tf), + fac->size_t_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->size_t_size); fac->alignment = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->alignment); @@ -866,10 +861,10 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) fac->name = g_quark_from_string(fac_name); fac->checksum = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->checksum); - fac->id = ltt_get_uint8(LTT_GET_BO(tf), &fac_load_data->id); + fac->id = fac_load_data->id; fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->pointer_size); - fac->size_t_size = ltt_get_uin32(LTT_GET_BO(tf), + fac->size_t_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->size_t_size); fac->alignment = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->alignment); @@ -1323,6 +1318,15 @@ LttTime ltt_interpolate_time(LttTracefile *tf, LttEvent *event) return time; } + +/* Get the current event of the tracefile : valid until the next read */ +LttEvent *ltt_tracefile_get_event(LttTracefile *tf) +{ + return &tf->event; +} + + + /***************************************************************************** *Function name * ltt_tracefile_read : Read the next event in the tracefile @@ -1419,7 +1423,7 @@ int ltt_tracefile_read_update_event(LttTracefile *tf) LttEvent *event; event = &tf->event; - pos = event->offset; + pos = tf->buffer.head + event->offset; /* Read event header */ @@ -1457,19 +1461,17 @@ int ltt_tracefile_read_update_event(LttTracefile *tf) pos += sizeof(guint32); } - event->facility_id = ltt_get_uint8(LTT_GET_BO(tf), - pos); + event->facility_id = *(guint8*)pos; pos += sizeof(guint8); - event->event_id = ltt_get_uint8(LTT_GET_BO(tf), - pos); + event->event_id = *(guint8*)pos; pos += sizeof(guint8); event->data = pos; /* get the data size and update the event fields with the current * information */ - event->data_size = ltt_update_event_size(tf); + ltt_update_event_size(tf); return 0; } @@ -1542,7 +1544,7 @@ static gint map_block(LttTracefile * tf, guint block_num) * it means that the event read must get the first event. */ tf->event.tracefile = tf; tf->event.block = block_num; - tf->event.offset = tf->buffer.head; + tf->event.offset = 0; return 0; @@ -1588,12 +1590,16 @@ void ltt_update_event_size(LttTracefile *tf) } else { LttEventType *event_type = ltt_facility_eventtype_get(f, tf->event.event_id); - size = get_fields_offsets(tf, event_type, tf->event.data); + size = get_field_type_size(tf, event_type, + 0, 0, event_type->root_field, tf->event.data); } tf->event.data_size = size; + + return; + event_id_error: - return -1; + tf->event.data_size = 0; } @@ -1615,13 +1621,13 @@ static int ltt_seek_next_event(LttTracefile *tf) ssize_t event_size; /* seek over the buffer header if we are at the buffer start */ - if(tf->event.offset == tf->buffer.head) { + if(tf->event.offset == 0) { tf->event.offset += sizeof(struct ltt_block_start_header); goto found; } - if(tf->event.offset == tf->buffer.head + tf->buffer.lost_size) { + if(tf->event.offset == tf->buffer.lost_size) { ret = ERANGE; goto found; } @@ -1632,7 +1638,7 @@ static int ltt_seek_next_event(LttTracefile *tf) pos += (size_t)tf->event.data_size; - tf->event.offset = pos; + tf->event.offset = pos - tf->buffer.head; found: return ret; @@ -1858,136 +1864,6 @@ void preset_field_type_size(LttTracefile *tf, LttEventType *event_type, } -/***************************************************************************** - *Function name - * get_field_type_size : set the fixed and dynamic sizes of the field type - * from the data read. - *Input params - * tf : tracefile - * event_type : event type - * offset_root : offset from the root - * offset_parent : offset from the parent - * field : field - * data : a pointer to the event data. - *Returns the field type size. - ****************************************************************************/ -size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type, - off_t offset_root, off_t offset_parent, - LttField *field, void *data) -{ - size_t size = 0; - guint i; - LttType *type; - - g_assert(field->fixed_root != FIELD_UNKNOWN); - g_assert(field->fixed_parent != FIELD_UNKNOWN); - g_assert(field->fixed_size != FIELD_UNKNOWN); - - field->offset_root = offset_root; - field->offset_parent = offset_parent; - - type = field->field_type; - - switch(type->type_class) { - case LTT_INT: - case LTT_UINT: - case LTT_FLOAT: - case LTT_ENUM: - case LTT_POINTER: - case LTT_LONG: - case LTT_ULONG: - case LTT_SIZE_T: - case LTT_SSIZE_T: - case LTT_OFF_T: - g_assert(field->fixed_size == FIELD_FIXED); - size = field->field_size; - break; - case LTT_SEQUENCE: - { - gint seqnum = ltt_get_uint(LTT_GET_BO(tf), - field->sequ_number_size, - data + offset_root); - - if(field->child[0]->fixed_size == FIELD_FIXED) { - size = field->sequ_number_size + - (seqnum * get_field_type_size(tf, event_type, - offset_root, offset_parent, - field->child[0], data)); - } else { - size += field->sequ_number_size; - for(i=0;ichild[0], data); - offset_root += child_size; - offset_parent += child_size; - size += child_size; - } - } - field->field_size = size; - } - break; - case LTT_STRING: - size = strlen((char*)(data+offset_root)) + 1;// length + \0 - field->field_size = size; - break; - case LTT_ARRAY: - if(field->fixed_size == FIELD_FIXED) - size = field->field_size; - else { - for(i=0;ifield_type->element_number;i++) { - size_t child_size; - child_size = get_field_type_size(tf, event_type, - offset_root, offset_parent, - field->child[0], data); - offset_root += child_size; - offset_parent += child_size; - size += child_size; - } - field->field_size = size; - } - break; - case LTT_STRUCT: - if(field->fixed_size == FIELD_FIXED) - size = field->field_size; - else { - size_t current_root_offset = offset_root; - size_t current_offset = 0; - size_t child_size = 0; - for(i=0;ielement_number;i++) { - child_size = get_field_type_size(tf, - event_type, current_root_offset, current_offset, - field->child[i], data); - current_offset += child_size; - current_root_offset += child_size; - - } - size = current_offset; - field->field_size = size; - } - break; - case LTT_UNION: - if(field->fixed_size == FIELD_FIXED) - size = field->field_size; - else { - size_t current_root_offset = field->offset_root; - size_t current_offset = 0; - for(i=0;ielement_number;i++) { - size = get_field_type_size(tf, event_type, - current_root_offset, current_offset, - field->child[i], data); - size = max(size, field->child[i]->field_size); - } - field->field_size = size; - } - break; - } - - return size; -} - - /***************************************************************************** *Function name * check_fields_compatibility : Check for compatibility between two fields : @@ -2290,7 +2166,7 @@ end_getFieldtypeSize: /***************************************************************************** *Function name - * get_int : get an integer number + * ltt_get_int : get an integer number *Input params * reverse_byte_order: must we reverse the byte order ? * size : the size of the integer @@ -2299,7 +2175,7 @@ end_getFieldtypeSize: * gint64 : a 64 bits integer ****************************************************************************/ -gint64 get_int(gboolean reverse_byte_order, gint size, void *data) +gint64 ltt_get_int(gboolean reverse_byte_order, gint size, void *data) { gint64 val; @@ -2318,7 +2194,7 @@ gint64 get_int(gboolean reverse_byte_order, gint size, void *data) /***************************************************************************** *Function name - * get_uint : get an unsigned integer number + * ltt_get_uint : get an unsigned integer number *Input params * reverse_byte_order: must we reverse the byte order ? * size : the size of the integer @@ -2327,7 +2203,7 @@ gint64 get_int(gboolean reverse_byte_order, gint size, void *data) * guint64 : a 64 bits unsigned integer ****************************************************************************/ -guint64 get_uint(gboolean reverse_byte_order, gint size, void *data) +guint64 ltt_get_uint(gboolean reverse_byte_order, gint size, void *data) { guint64 val; diff --git a/ltt/branches/poly/lttv/lttv/batchtest.c b/ltt/branches/poly/lttv/lttv/batchtest.c index 3a4a2565..c48f9d77 100644 --- a/ltt/branches/poly/lttv/lttv/batchtest.c +++ b/ltt/branches/poly/lttv/lttv/batchtest.c @@ -78,6 +78,9 @@ static gboolean a_test7, a_test_all; +static GQuark QUARK_BLOCK_START, + QUARK_BLOCK_END; + LttEventPosition *a_event_position; typedef struct _save_state { @@ -155,16 +158,18 @@ gboolean trace_event(void __UNUSED__ *hook_data, void *call_data) { LttvTracefileState *tfs = (LttvTracefileState *)call_data; - guint nb_block, nb_event; + guint nb_block, offset; - LttTracefile *tf; + guint64 tsc; - ltt_event_position(tfs->parent.e, a_event_position); - ltt_event_position_get(a_event_position, &nb_block, &nb_event, &tf); - fprintf(stderr,"Event %s %lu.%09lu [%u %u]\n", - ltt_eventtype_name(ltt_event_eventtype(tfs->parent.e)), + LttTracefile *tf; + LttEvent *e = ltt_tracefile_get_event(tfs->parent.tf); + ltt_event_position(e, a_event_position); + ltt_event_position_get(a_event_position, &tf, &nb_block, &offset, &tsc); + fprintf(stderr,"Event %s %lu.%09lu [%u %u tsc %llu]\n", + g_quark_to_string(ltt_eventtype_name(ltt_event_eventtype(e))), tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec, - nb_block, nb_event); + nb_block, offset, tsc); return FALSE; } @@ -186,12 +191,15 @@ gboolean save_state_copy_event(void *hook_data, void *call_data) LttvTraceState *ts = (LttvTraceState *)tfs->parent.t_context; + LttEvent *e = ltt_tracefile_get_event(tfs->parent.tf); + GString *filename; FILE *fp; - if(ts->nb_event == 0 && strcmp(ltt_eventtype_name( - ltt_event_eventtype(tfs->parent.e)), "block_start") == 0) { + if(ts->nb_event == 0 && + ltt_eventtype_name(ltt_event_eventtype(e)) + == QUARK_BLOCK_START) { if(a_save_sample != NULL) { filename = g_string_new(""); g_string_printf(filename, "%s.copy.%lu.%09lu.xml", a_save_sample, @@ -240,40 +248,112 @@ gboolean save_state_event(void *hook_data, void *call_data) } + +static void compute_tracefile(LttTracefile *tracefile) +{ + GString *filename; + guint i, j, nb_equal, nb_block, offset; + guint64 tsc; + FILE *fp; + LttTime time, previous_time; + LttEvent *event = ltt_event_new(); + LttFacility *facility; + LttEventType *event_type; + int err; + + /* start_count is always initialized in this function _if_ there is always + * a block_start before a block_end. + */ + long long unsigned cycle_count, start_count=0, delta_cycle; + + + filename = g_string_new(""); + g_string_printf(filename, "%s.%u.%u.trace", a_dump_tracefiles, i, j); + fp = fopen(filename->str, "w"); + if(fp == NULL) g_error("Cannot open %s", filename->str); + g_string_free(filename, TRUE); + err = ltt_tracefile_seek_time(tracefile, ltt_time_zero); + if(err) goto close; + + previous_time = ltt_time_zero; + nb_equal = 0; + + do { + LttTracefile *tf_pos; + facility = ltt_event_facility(event); + event_type = ltt_event_eventtype(event); + time = ltt_event_time(event); + ltt_event_position(event, a_event_position); + ltt_event_position_get(a_event_position, &tf_pos, &nb_block, &offset, &tsc); + fprintf(fp,"%s.%s: %llu %lu.%09lu position %u/%u\n", + ltt_facility_name(facility), ltt_eventtype_name(event_type), + tsc, (unsigned long)time.tv_sec, + (unsigned long)time.tv_nsec, + nb_block, offset); + + if(ltt_time_compare(time, previous_time) < 0) { + g_warning("Time decreasing trace %d tracefile %d position %u/%u", + i, j, nb_block, offset); + } + +#if 0 //FIXME + if(ltt_eventtype_name(event_type) == QUARK_BLOCK_START) { + start_count = cycle_count; + start_time = time; + } + else if(ltt_eventtype_name(event_type) == QUARK_BLOCK_END) { + delta_cycle = cycle_count - start_count; + end_nsec_sec = (long long unsigned)time.tv_sec * (long long unsigned)1000000000; + end_nsec_nsec = time.tv_nsec; + end_nsec = end_nsec_sec + end_nsec_nsec; + start_nsec = (long long unsigned)start_time.tv_sec * (long long unsigned)1000000000 + (long long unsigned)start_time.tv_nsec; + delta_nsec = end_nsec - start_nsec; + cycle_per_nsec = (double)delta_cycle / (double)delta_nsec; + nsec_per_cycle = (double)delta_nsec / (double)delta_cycle; + added_nsec = (double)delta_cycle * nsec_per_cycle; + interpolated_nsec = start_nsec + added_nsec; + added_nsec2 = (double)delta_cycle / cycle_per_nsec; + interpolated_nsec2 = start_nsec + added_nsec2; + + fprintf(fp,"Time: start_count %llu, end_count %llu, delta_cycle %llu, start_nsec %llu, end_nsec_sec %llu, end_nsec_nsec %llu, end_nsec %llu, delta_nsec %llu, cycle_per_nsec %.25f, nsec_per_cycle %.25f, added_nsec %llu, added_nsec2 %llu, interpolated_nsec %llu, interpolated_nsec2 %llu\n", start_count, cycle_count, delta_cycle, start_nsec, end_nsec_sec, end_nsec_nsec, end_nsec, delta_nsec, cycle_per_nsec, nsec_per_cycle, added_nsec, added_nsec2, interpolated_nsec, interpolated_nsec2); + } + else { +#endif //0 + if(ltt_time_compare(time, previous_time) == 0) nb_equal++; + else if(nb_equal > 0) { + g_warning("Consecutive %d events with time %lu.%09lu", + nb_equal + 1, previous_time.tv_sec, previous_time.tv_nsec); + nb_equal = 0; + } + previous_time = time; + //} + } while((!ltt_tracefile_read(tracefile))); + +close: + fclose(fp); + ltt_event_destroy(event); +} + static gboolean process_traceset(void __UNUSED__ *hook_data, void __UNUSED__ *call_data) { + GString *filename; LttvTracesetStats *tscs; LttvTracesetState *ts; LttvTracesetContext *tc; - GString *filename; - FILE *fp; double t; - guint i, j, count, nb_control, nb_tracefile, nb_block, nb_event, nb_equal; + //guint count, nb_control, nb_tracefile, nb_block, nb_event; + //guint i, j, count, nb_control, nb_tracefile, nb_block, nb_event, nb_equal; + guint i, j, count; LttTrace *trace; - LttTracefile *tracefile, *tf; - - LttEvent *event = ltt_event_new(); - - LttFacility *facility; - - LttEventType *event_type; - - LttTime time, previous_time; - - /* start_count is always initialized in this function _if_ there is always - * a block_start before a block_end. - */ - long long unsigned cycle_count, start_count=0, delta_cycle; - long long unsigned start_nsec, end_nsec, delta_nsec, added_nsec, added_nsec2; double cycle_per_nsec, nsec_per_cycle; @@ -282,83 +362,21 @@ static gboolean process_traceset(void __UNUSED__ *hook_data, LttTime start_time; - LttTime zero_time = ltt_time_zero; - LttTime max_time = { G_MAXULONG, G_MAXULONG }; a_event_position = ltt_event_position_new(); + GData *tracefiles_groups; + if(a_dump_tracefiles != NULL) { for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) { trace = lttv_trace(lttv_traceset_get(traceset, i)); - nb_control = ltt_trace_control_tracefile_number(trace); - nb_tracefile = nb_control + ltt_trace_per_cpu_tracefile_number(trace); - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tracefile = ltt_trace_control_tracefile_get(trace,j); - } - else { - tracefile = ltt_trace_per_cpu_tracefile_get(trace,j - nb_control); - } + tracefiles_groups = ltt_trace_get_tracefiles_groups(trace); - filename = g_string_new(""); - g_string_printf(filename, "%s.%u.%u.trace", a_dump_tracefiles, i, j); - fp = fopen(filename->str, "w"); - if(fp == NULL) g_error("Cannot open %s", filename->str); - g_string_free(filename, TRUE); - ltt_tracefile_seek_time(tracefile, zero_time); - previous_time = zero_time; - nb_equal = 0; - while((ltt_tracefile_read(tracefile, event)) != NULL) { - facility = ltt_event_facility(event); - event_type = ltt_event_eventtype(event); - time = ltt_event_time(event); - cycle_count = ltt_event_cycle_count(event); - ltt_event_position(event, a_event_position); - ltt_event_position_get(a_event_position, &nb_block, &nb_event, &tf); - fprintf(fp,"%s.%s: %llu %lu.%09lu position %u/%u\n", - ltt_facility_name(facility), ltt_eventtype_name(event_type), - cycle_count, (unsigned long)time.tv_sec, - (unsigned long)time.tv_nsec, - nb_block, nb_event); - - if(ltt_time_compare(time, previous_time) < 0) { - g_warning("Time decreasing trace %d tracefile %d position %u/%u", - i, j, nb_block, nb_event); - } - - if(strcmp(ltt_eventtype_name(event_type),"block_start") == 0) { - start_count = cycle_count; - start_time = time; - } - else if(strcmp(ltt_eventtype_name(event_type),"block_end") == 0) { - delta_cycle = cycle_count - start_count; - end_nsec_sec = (long long unsigned)time.tv_sec * (long long unsigned)1000000000; - end_nsec_nsec = time.tv_nsec; - end_nsec = end_nsec_sec + end_nsec_nsec; - start_nsec = (long long unsigned)start_time.tv_sec * (long long unsigned)1000000000 + (long long unsigned)start_time.tv_nsec; - delta_nsec = end_nsec - start_nsec; - cycle_per_nsec = (double)delta_cycle / (double)delta_nsec; - nsec_per_cycle = (double)delta_nsec / (double)delta_cycle; - added_nsec = (double)delta_cycle * nsec_per_cycle; - interpolated_nsec = start_nsec + added_nsec; - added_nsec2 = (double)delta_cycle / cycle_per_nsec; - interpolated_nsec2 = start_nsec + added_nsec2; - - fprintf(fp,"Time: start_count %llu, end_count %llu, delta_cycle %llu, start_nsec %llu, end_nsec_sec %llu, end_nsec_nsec %llu, end_nsec %llu, delta_nsec %llu, cycle_per_nsec %.25f, nsec_per_cycle %.25f, added_nsec %llu, added_nsec2 %llu, interpolated_nsec %llu, interpolated_nsec2 %llu\n", start_count, cycle_count, delta_cycle, start_nsec, end_nsec_sec, end_nsec_nsec, end_nsec, delta_nsec, cycle_per_nsec, nsec_per_cycle, added_nsec, added_nsec2, interpolated_nsec, interpolated_nsec2); - } - else { - if(ltt_time_compare(time, previous_time) == 0) nb_equal++; - else if(nb_equal > 0) { - g_warning("Consecutive %d events with time %lu.%09lu", - nb_equal + 1, previous_time.tv_sec, previous_time.tv_nsec); - nb_equal = 0; - } - previous_time = time; - } - } - fclose(fp); - } + g_datalist_foreach(&tracefiles_groups, + (GDataForeachFunc)compute_tracefile_group, + compute_tracefile); + } } @@ -375,7 +393,7 @@ static gboolean process_traceset(void __UNUSED__ *hook_data, if(a_test1 || a_test_all) { count = 0; lttv_hooks_add(event_hook, count_event, &count, LTTV_PRIO_DEFAULT); - t = run_one_test(ts, zero_time, max_time); + t = run_one_test(ts, ltt_time_zero, max_time); lttv_hooks_remove_data(event_hook, count_event, &count); g_warning( "Processing trace while counting events (%u events in %g seconds)", @@ -386,7 +404,7 @@ static gboolean process_traceset(void __UNUSED__ *hook_data, if(a_test2 || a_test_all) { lttv_state_add_event_hooks(ts); - t = run_one_test(ts, zero_time, max_time); + t = run_one_test(ts, ltt_time_zero, max_time); lttv_state_remove_event_hooks(ts); g_warning("Processing trace while updating state (%g seconds)", t); } @@ -410,7 +428,7 @@ static gboolean process_traceset(void __UNUSED__ *hook_data, lttv_state_add_event_hooks(ts); lttv_hooks_add(event_hook, save_state_event, &save_state, LTTV_PRIO_DEFAULT); - t = run_one_test(ts, zero_time, max_time); + t = run_one_test(ts, ltt_time_zero, max_time); lttv_state_remove_event_hooks(ts); lttv_hooks_remove_data(event_hook, save_state_event, &save_state); g_warning("Processing while updating/writing state (%g seconds)", t); @@ -426,7 +444,7 @@ static gboolean process_traceset(void __UNUSED__ *hook_data, } lttv_stats_add_event_hooks(tscs); - t = run_one_test(ts, zero_time, max_time); + t = run_one_test(ts, ltt_time_zero, max_time); lttv_stats_remove_event_hooks(tscs); g_warning("Processing trace while counting stats (%g seconds)", t); @@ -461,7 +479,7 @@ static gboolean process_traceset(void __UNUSED__ *hook_data, lttv_state_add_event_hooks(ts); lttv_stats_add_event_hooks(tscs); - t = run_one_test(ts, zero_time, max_time); + t = run_one_test(ts, ltt_time_zero, max_time); lttv_state_remove_event_hooks(ts); lttv_stats_remove_event_hooks(tscs); g_warning( @@ -497,7 +515,7 @@ static gboolean process_traceset(void __UNUSED__ *hook_data, if(a_save_state_copy) lttv_hooks_add(event_hook, save_state_copy_event, &save_state, LTTV_PRIO_DEFAULT); - t = run_one_test(ts, zero_time, max_time); + t = run_one_test(ts, ltt_time_zero, max_time); lttv_state_remove_event_hooks(ts); lttv_state_save_remove_event_hooks(ts); if(a_save_state_copy) @@ -549,7 +567,6 @@ static gboolean process_traceset(void __UNUSED__ *hook_data, g_free(a_event_position); lttv_context_fini(tc); g_object_unref(tscs); - ltt_event_destroy(event); if(lttv_profile_memory) { g_message("Memory summary at the end of batchtest"); @@ -569,6 +586,11 @@ static void init() g_info("Init batchtest.c"); + /* Init GQuarks */ + QUARK_BLOCK_START = g_quark_from_string("block_start"); + QUARK_BLOCK_END = g_quark_from_string("block_end"); + + lttv_option_add("trace", 't', "add a trace to the trace set to analyse", "pathname of the directory containing the trace", diff --git a/ltt/branches/poly/lttv/lttv/filter.c b/ltt/branches/poly/lttv/lttv/filter.c index f0eca9cb..e837068c 100644 --- a/ltt/branches/poly/lttv/lttv/filter.c +++ b/ltt/branches/poly/lttv/lttv/filter.c @@ -1726,16 +1726,14 @@ lttv_filter_tree_parse_branch( case LTTV_FILTER_TRACE_NAME: if(trace == NULL) return TRUE; else { - char* trace_name = ltt_trace_name(trace); - GQuark quark = g_quark_from_string(trace_name); + GQuark quark = ltt_trace_name(trace); return se->op((gpointer)&quark,v); } break; case LTTV_FILTER_TRACEFILE_NAME: if(tracefile == NULL) return TRUE; else { - char* tracefile_name = ltt_tracefile_name(tracefile); - GQuark quark = g_quark_from_string(tracefile_name); + GQuark quark = ltt_tracefile_name(tracefile); return se->op((gpointer)&quark,v); } break; @@ -1794,8 +1792,7 @@ lttv_filter_tree_parse_branch( else { LttEventType* et; et = ltt_event_eventtype(event); - char* event_name = ltt_eventtype_name(et); - GQuark quark = g_quark_from_string(event_name); + GQuark quark = ltt_eventtype_name(et); return se->op((gpointer)&quark,v); } break; diff --git a/ltt/branches/poly/lttv/lttv/lttv.h b/ltt/branches/poly/lttv/lttv/lttv.h index 27c610a2..b0dd43ba 100644 --- a/ltt/branches/poly/lttv/lttv/lttv.h +++ b/ltt/branches/poly/lttv/lttv/lttv.h @@ -55,6 +55,9 @@ extern char **lttv_argv; */ #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) + +#ifndef g_debug #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) +#endif #endif // LTTV_H diff --git a/ltt/branches/poly/lttv/lttv/state.c b/ltt/branches/poly/lttv/lttv/state.c index 148b17bb..e8eb3db4 100644 --- a/ltt/branches/poly/lttv/lttv/state.c +++ b/ltt/branches/poly/lttv/lttv/state.c @@ -31,6 +31,39 @@ #define PREALLOCATED_EXECUTION_STACK 10 +/* Facilities Quarks */ + +GQuark + LTT_FACILITY_KERNEL, + LTT_FACILITY_PROCESS; + +/* Events Quarks */ + +GQuark + LTT_EVENT_SYSCALL_ENTRY, + LTT_EVENT_SYSCALL_EXIT, + LTT_EVENT_TRAP_ENTRY, + LTT_EVENT_TRAP_EXIT, + LTT_EVENT_IRQ_ENTRY, + LTT_EVENT_IRQ_EXIT, + LTT_EVENT_SCHEDCHANGE, + LTT_EVENT_FORK, + LTT_EVENT_EXIT, + LTT_EVENT_FREE; + +/* Fields Quarks */ + +GQuark + LTT_FIELD_SYSCALL_ID, + LTT_FIELD_TRAP_ID, + LTT_FIELD_IRQ_ID, + LTT_FIELD_OUT, + LTT_FIELD_IN, + LTT_FIELD_OUT_STATE, + LTT_FIELD_PARENT_PID, + LTT_FIELD_CHILD_PID, + LTT_FIELD_PID; + LttvExecutionMode LTTV_STATE_MODE_UNKNOWN, LTTV_STATE_USER_MODE, @@ -63,7 +96,6 @@ static GQuark LTTV_STATE_NAME_TABLES, LTTV_STATE_TRACE_STATE_USE_COUNT; - static void create_max_time(LttvTraceState *tcs); static void get_max_time(LttvTraceState *tcs); @@ -136,13 +168,14 @@ restore_init_state(LttvTraceState *self) self->processes = g_hash_table_new(process_hash, process_equal); self->nb_event = 0; - nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) + - ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = self->parent.tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { - tfcs = LTTV_TRACEFILE_STATE(self->parent.tracefiles[i]); + tfcs = + LTTV_TRACEFILE_STATE(&g_array_index(self->parent.tracefiles, + LttvTracefileContext, i)); ltt_trace_time_span_get(self->parent.t, &tfcs->parent.timestamp, NULL); - tfcs->saved_position = 0; +// tfcs->saved_position = 0; tfcs->process = lttv_state_create_process(tfcs, NULL,0); tfcs->process->state->s = LTTV_STATE_RUN; tfcs->process->last_cpu = tfcs->cpu_name; @@ -172,7 +205,7 @@ init(LttvTracesetState *self, LttvTraceset *ts) for(i = 0 ; i < nb_trace ; i++) { tc = self->parent.traces[i]; tcs = (LttvTraceState *)tc; - tcs->save_interval = 50000; + tcs->save_interval = LTTV_STATE_SAVE_INTERVAL; lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT, LTTV_UINT, &v); (*v.v_uint)++; @@ -184,12 +217,13 @@ init(LttvTracesetState *self, LttvTraceset *ts) get_name_tables(tcs); get_max_time(tcs); - nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + - ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = tc->tracefiles->len; for(j = 0 ; j < nb_tracefile ; j++) { - tfcs = LTTV_TRACEFILE_STATE(tc->tracefiles[j]); - tfcs->cpu_name= g_quark_from_string(ltt_tracefile_name(tfcs->parent.tf)); + tfcs = + LTTV_TRACEFILE_STATE(&g_array_index(tc->tracefiles, + LttvTracefileContext, j)); + tfcs->cpu_name = ltt_tracefile_name(tfcs->parent.tf); } tcs->processes = NULL; restore_init_state(tcs); @@ -285,7 +319,8 @@ static void write_process_state(gpointer key, gpointer value, void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp) { - guint i, nb_tracefile, nb_block, nb_event; + guint i, nb_tracefile, nb_block, offset; + guint64 tsc; LttvTracefileState *tfcs; @@ -299,19 +334,22 @@ void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp) g_hash_table_foreach(self->processes, write_process_state, fp); - nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) + - ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = self->parent.tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { - tfcs = (LttvTracefileState *)self->parent.tracefiles[i]; + tfcs = + LTTV_TRACEFILE_STATE(&g_array_index(self->parent.tracefiles, + LttvTracefileContext, i)); fprintf(fp, " process->pid, tfcs->parent.timestamp.tv_sec, tfcs->parent.timestamp.tv_nsec); - if(tfcs->parent.e == NULL) fprintf(fp,"/>\n"); + LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf); + if(e == NULL) fprintf(fp,"/>\n"); else { - ltt_event_position(tfcs->parent.e, ep); - ltt_event_position_get(ep, &nb_block, &nb_event, &tf); - fprintf(fp, " BLOCK=%u EVENT=%u/>\n", nb_block, nb_event); + ltt_event_position(e, ep); + ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc); + fprintf(fp, " BLOCK=%lu OFFSET=%lu TSC=%llu/>\n", nb_block, offset, + tsc); } } g_free(ep); @@ -383,11 +421,12 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) LTTV_POINTER); *(value.v_pointer) = lttv_state_copy_process_table(self->processes); - nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) + - ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = self->parent.tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { - tfcs = (LttvTracefileState *)self->parent.tracefiles[i]; + tfcs = + LTTV_TRACEFILE_STATE(&g_array_index(self->parent.tracefiles, + LttvTracefileContext, i)); tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); value = lttv_attribute_add(tracefiles_tree, i, LTTV_GOBJECT); @@ -397,16 +436,19 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) *(value.v_uint) = tfcs->process->pid; value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT, LTTV_POINTER); - if(tfcs->parent.e == NULL) *(value.v_pointer) = NULL; + LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf); + if(e == NULL) *(value.v_pointer) = NULL; else { ep = ltt_event_position_new(); - ltt_event_position(tfcs->parent.e, ep); + ltt_event_position(e, ep); *(value.v_pointer) = ep; - guint nb_block, nb_event; + guint nb_block, offset; + guint64 tsc; LttTracefile *tf; - ltt_event_position_get(ep, &nb_block, &nb_event, &tf); - g_debug("Block %u event %u time %lu.%lu", nb_block, nb_event, + ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc); + g_debug("Block %lu offset %lu tsc %llu time %lu.%lu", nb_block, offset, + tsc, tfcs->parent.timestamp.tv_sec, tfcs->parent.timestamp.tv_nsec); } } @@ -438,11 +480,12 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) lttv_state_free_process_table(self->processes); self->processes = lttv_state_copy_process_table(*(value.v_pointer)); - nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) + - ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = self->parent.tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { - tfcs = (LttvTracefileState *)self->parent.tracefiles[i]; + tfcs = + LTTV_TRACEFILE_STATE(&g_array_index(self->parent.tracefiles, + LttvTracefileContext, i)); type = lttv_attribute_get(tracefiles_tree, i, &name, &value); g_assert(type == LTTV_GOBJECT); tracefile_tree = *((LttvAttribute **)(value.v_gobject)); @@ -456,12 +499,10 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, &value); g_assert(type == LTTV_POINTER); - if(*(value.v_pointer) == NULL) tfcs->parent.e = NULL; - else { - ep = *(value.v_pointer); - g_assert(tfcs->parent.t_context != NULL); - lttv_process_tracefile_seek_position(LTTV_TRACEFILE_CONTEXT(tfcs), ep); - } + g_assert(*(value.v_pointer) != NULL); + ep = *(value.v_pointer); + g_assert(tfcs->parent.t_context != NULL); + lttv_process_tracefile_seek_position(LTTV_TRACEFILE_CONTEXT(tfcs), ep); } } @@ -494,11 +535,12 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) *(value.v_pointer) = NULL; lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES); - nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) + - ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = self->parent.tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { - tfcs = (LttvTracefileState *)self->parent.tracefiles[i]; + tfcs = + LTTV_TRACEFILE_STATE(&g_array_index(self->parent.tracefiles, + LttvTracefileContext, i)); type = lttv_attribute_get(tracefiles_tree, i, &name, &value); g_assert(type == LTTV_GOBJECT); tracefile_tree = *((LttvAttribute **)(value.v_gobject)); @@ -576,7 +618,7 @@ free_max_time(LttvTraceState *tcs) typedef struct _LttvNameTables { - GQuark *eventtype_names; + // FIXME GQuark *eventtype_names; GQuark *syscall_names; GQuark *trap_names; GQuark *irq_names; @@ -588,9 +630,11 @@ create_name_tables(LttvTraceState *tcs) { int i, nb; - char *f_name, *e_name; + GQuark f_name, e_name; + + LttvTraceHook *h; - LttvTraceHook h; + LttvTraceHookByFacility *thf; LttEventType *et; @@ -606,7 +650,8 @@ create_name_tables(LttvTraceState *tcs) LTTV_POINTER, &v); g_assert(*(v.v_pointer) == NULL); *(v.v_pointer) = name_tables; - +#if 0 // Use iteration over the facilities_by_name and then list all event + // types of each facility nb = ltt_trace_eventtype_number(tcs->parent.t); name_tables->eventtype_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { @@ -616,13 +661,21 @@ create_name_tables(LttvTraceState *tcs) g_string_printf(fe_name, "%s.%s", f_name, e_name); name_tables->eventtype_names[i] = g_quark_from_string(fe_name->str); } - - lttv_trace_find_hook(tcs->parent.t, "core", "syscall_entry", - "syscall_id", NULL, NULL, NULL, &h); - t = ltt_field_type(h.f1); +#endif //0 + if(lttv_trace_find_hook(tcs->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY, + LTT_FIELD_SYSCALL_ID, 0, 0, + NULL, h)) + return; + + thf = lttv_trace_hook_get_first(h); + + t = ltt_field_type(thf->f1); nb = ltt_type_element_number(t); + + lttv_trace_hook_destroy(h); - /* CHECK syscalls should be an emun but currently are not! + /* CHECK syscalls should be an enum but currently are not! name_tables->syscall_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { @@ -637,11 +690,19 @@ create_name_tables(LttvTraceState *tcs) name_tables->syscall_names[i] = g_quark_from_string(fe_name->str); } - lttv_trace_find_hook(tcs->parent.t, "core", "trap_entry", - "trap_id", NULL, NULL, NULL, &h); - t = ltt_field_type(h.f1); + if(lttv_trace_find_hook(tcs->parent.t, LTT_FACILITY_KERNEL, + LTT_EVENT_TRAP_ENTRY, + LTT_FIELD_TRAP_ID, 0, 0, + NULL, h)) + return; + + thf = lttv_trace_hook_get_first(h); + + t = ltt_field_type(thf->f1); nb = ltt_type_element_number(t); + lttv_trace_hook_destroy(h); + /* name_tables->trap_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { @@ -656,11 +717,19 @@ create_name_tables(LttvTraceState *tcs) name_tables->trap_names[i] = g_quark_from_string(fe_name->str); } - lttv_trace_find_hook(tcs->parent.t, "core", "irq_entry", - "irq_id", NULL, NULL, NULL, &h); - t = ltt_field_type(h.f1); + if(lttv_trace_find_hook(tcs->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY, + LTT_FIELD_IRQ_ID, 0, 0, + NULL, h)) + return; + + thf = lttv_trace_hook_get_first(h); + + t = ltt_field_type(thf->f1); nb = ltt_type_element_number(t); + lttv_trace_hook_destroy(h); + /* name_tables->irq_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { @@ -689,7 +758,7 @@ get_name_tables(LttvTraceState *tcs) LTTV_POINTER, &v); g_assert(*(v.v_pointer) != NULL); name_tables = (LttvNameTables *)*(v.v_pointer); - tcs->eventtype_names = name_tables->eventtype_names; + //tcs->eventtype_names = name_tables->eventtype_names; tcs->syscall_names = name_tables->syscall_names; tcs->trap_names = name_tables->trap_names; tcs->irq_names = name_tables->irq_names; @@ -708,7 +777,7 @@ free_name_tables(LttvTraceState *tcs) name_tables = (LttvNameTables *)*(v.v_pointer); *(v.v_pointer) = NULL; - g_free(name_tables->eventtype_names); + // g_free(name_tables->eventtype_names); g_free(name_tables->syscall_names); g_free(name_tables->trap_names); g_free(name_tables->irq_names); @@ -887,14 +956,17 @@ static void lttv_state_free_process_table(GHashTable *processes) static gboolean syscall_entry(void *hook_data, void *call_data) { - LttField *f = ((LttvTraceHook *)hook_data)->f1; - LttvTracefileState *s = (LttvTracefileState *)call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHookByFacility *thf = + lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, + ltt_event_facility_id(e)); + LttField *f = thf->f1; LttvExecutionSubmode submode; submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[ - ltt_event_get_unsigned(s->parent.e, f)]; + ltt_event_get_unsigned(e, f)]; push_state(s, LTTV_STATE_SYSCALL, submode); return FALSE; } @@ -911,14 +983,17 @@ static gboolean syscall_exit(void *hook_data, void *call_data) static gboolean trap_entry(void *hook_data, void *call_data) { - LttField *f = ((LttvTraceHook *)hook_data)->f1; - LttvTracefileState *s = (LttvTracefileState *)call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHookByFacility *thf = + lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, + ltt_event_facility_id(e)); + LttField *f = thf->f1; LttvExecutionSubmode submode; submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[ - ltt_event_get_unsigned(s->parent.e, f)]; + ltt_event_get_unsigned(e, f)]; push_state(s, LTTV_STATE_TRAP, submode); return FALSE; } @@ -935,14 +1010,17 @@ static gboolean trap_exit(void *hook_data, void *call_data) static gboolean irq_entry(void *hook_data, void *call_data) { - LttField *f = ((LttvTraceHook *)hook_data)->f1; - LttvTracefileState *s = (LttvTracefileState *)call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHookByFacility *thf = + lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, + ltt_event_facility_id(e)); + LttField *f = thf->f1; LttvExecutionSubmode submode; submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[ - ltt_event_get_unsigned(s->parent.e, f)]; + ltt_event_get_unsigned(e, f)]; /* Do something with the info about being in user or system mode when int? */ push_state(s, LTTV_STATE_IRQ, submode); @@ -961,15 +1039,16 @@ static gboolean irq_exit(void *hook_data, void *call_data) static gboolean schedchange(void *hook_data, void *call_data) { - LttvTraceHook *h = (LttvTraceHook *)hook_data; - LttvTracefileState *s = (LttvTracefileState *)call_data; - + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHookByFacility *thf = + lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, + ltt_event_facility_id(e)); guint pid_in, pid_out, state_out; - pid_in = ltt_event_get_unsigned(s->parent.e, h->f1); - pid_out = ltt_event_get_unsigned(s->parent.e, h->f2); - state_out = ltt_event_get_unsigned(s->parent.e, h->f3); + pid_out = ltt_event_get_unsigned(e, thf->f1); + pid_in = ltt_event_get_unsigned(e, thf->f2); + state_out = ltt_event_get_unsigned(e, thf->f3); if(likely(s->process != NULL)) { @@ -1006,50 +1085,76 @@ static gboolean schedchange(void *hook_data, void *call_data) return FALSE; } - -static gboolean process_fork(LttvTraceHook *trace_hook, LttvTracefileState *s) +static gboolean process_fork(void *hook_data, void *call_data) { + LttvTracefileState *s = (LttvTracefileState *)call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHookByFacility *thf = + lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, + ltt_event_facility_id(e)); LttField *f; + guint parent_pid; guint child_pid; LttvProcessState *zombie_process; + /* Parent PID */ + f = thf->f1; + parent_pid = ltt_event_get_unsigned(e, f); + /* Child PID */ - f = trace_hook->f2; - child_pid = ltt_event_get_unsigned(s->parent.e, f); + f = thf->f2; + child_pid = ltt_event_get_unsigned(e, f); zombie_process = lttv_state_find_process(s, child_pid); if(unlikely(zombie_process != NULL)) { /* Reutilisation of PID. Only now we are sure that the old PID - * has been released. FIXME : sould know when release_task happens instead. + * has been released. FIXME : should know when release_task happens instead. */ exit_process(s, zombie_process); } g_assert(s->process->pid != child_pid); + // FIXME : Add this test in the "known state" section + // g_assert(s->process->pid == parent_pid); lttv_state_create_process(s, s->process, child_pid); return FALSE; } -static gboolean process_exit(LttvTraceHook *trace_hook, LttvTracefileState *s) +static gboolean process_exit(void *hook_data, void *call_data) { + LttvTracefileState *s = (LttvTracefileState *)call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHookByFacility *thf = + lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, + ltt_event_facility_id(e)); + LttField *f; + guint pid; + + pid = ltt_event_get_unsigned(e, thf->f1); + + // FIXME : Add this test in the "known state" section + // g_assert(s->process->pid == pid); + if(likely(s->process != NULL)) { s->process->state->s = LTTV_STATE_EXIT; } return FALSE; } -static gboolean process_release(LttvTraceHook *trace_hook, - LttvTracefileState *s) +static gboolean process_free(void *hook_data, void *call_data) { - LttField *f; + LttvTracefileState *s = (LttvTracefileState *)call_data; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + LttvTraceHookByFacility *thf = + lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, + ltt_event_facility_id(e)); guint release_pid; LttvProcessState *process; /* PID of the process to release */ - f = trace_hook->f2; - release_pid = ltt_event_get_unsigned(s->parent.e, f); + release_pid = ltt_event_get_unsigned(e, thf->f1); process = lttv_state_find_process(s, release_pid); @@ -1062,26 +1167,6 @@ static gboolean process_release(LttvTraceHook *trace_hook, return FALSE; } -gboolean process(void *hook_data, void *call_data) -{ - LttvTraceHook *trace_hook = (LttvTraceHook *)hook_data; - LttField *f = trace_hook->f1; - - LttvTracefileState *s = (LttvTracefileState *)call_data; - - guint sub_id = ltt_event_get_unsigned(s->parent.e, f); - - /* CHECK : do not hardcode the sub_id values here ? */ - if(sub_id == 2) { - return process_fork(trace_hook, s); - } else if(sub_id == 3) { - return process_exit(trace_hook, s); - } else if(sub_id == 7) { - return process_release(trace_hook, s); - } - return 0; -} - gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data) { LttvTracesetState *tss = (LttvTracesetState*)(call_data); @@ -1095,7 +1180,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) { LttvTraceset *traceset = self->parent.ts; - guint i, j, k, nb_trace, nb_tracefile; + guint i, j, k, l, nb_trace, nb_tracefile; LttvTraceState *ts; @@ -1103,7 +1188,9 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) GArray *hooks; - LttvTraceHook hook; + LttvTraceHookByFacility *thf; + + LttvTraceHook *hook; LttvAttributeValue val; @@ -1114,53 +1201,79 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) /* Find the eventtype id for the following events and register the associated by id hooks. */ - hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); - g_array_set_size(hooks, 8); + hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 10); + g_array_set_size(hooks, 10); - lttv_trace_find_hook(ts->parent.t, "core","syscall_entry","syscall_id", - NULL, NULL, syscall_entry, &g_array_index(hooks, LttvTraceHook, 0)); + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY, + LTT_FIELD_SYSCALL_ID, 0, 0, + syscall_entry, &g_array_index(hooks, LttvTraceHook, 0)); - lttv_trace_find_hook(ts->parent.t, "core", "syscall_exit", NULL, NULL, - NULL, syscall_exit, &g_array_index(hooks, LttvTraceHook, 1)); + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT, + 0, 0, 0, + syscall_exit, &g_array_index(hooks, LttvTraceHook, 1)); - lttv_trace_find_hook(ts->parent.t, "core", "trap_entry", "trap_id", - NULL, NULL, trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY, + LTT_FIELD_TRAP_ID, 0, 0, + trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); - lttv_trace_find_hook(ts->parent.t, "core", "trap_exit", NULL, NULL, NULL, + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT, + 0, 0, 0, trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); - lttv_trace_find_hook(ts->parent.t, "core", "irq_entry", "irq_id", NULL, - NULL, irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY, + LTT_FIELD_IRQ_ID, 0, 0, + irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); - lttv_trace_find_hook(ts->parent.t, "core", "irq_exit", NULL, NULL, NULL, + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT, + 0, 0, 0, irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); - lttv_trace_find_hook(ts->parent.t, "core", "schedchange", "in", "out", - "out_state", schedchange, &g_array_index(hooks, LttvTraceHook, 6)); + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE, + LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE, + schedchange, &g_array_index(hooks, LttvTraceHook, 6)); - lttv_trace_find_hook(ts->parent.t, "core", "process", "event_sub_id", - "event_data1", "event_data2", process, - &g_array_index(hooks, LttvTraceHook, 7)); + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_PROCESS, LTT_EVENT_FORK, + LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0, + process_fork, &g_array_index(hooks, LttvTraceHook, 7)); + + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_PROCESS, LTT_EVENT_EXIT, + LTT_FIELD_PID, 0, 0, + process_exit, &g_array_index(hooks, LttvTraceHook, 8)); + + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_PROCESS, LTT_EVENT_FREE, + LTT_FIELD_PID, 0, 0, + process_free, &g_array_index(hooks, LttvTraceHook, 9)); -#if 0 - lttv_trace_find_hook(ts->parent.t, "core", "process_fork", "child_pid", - NULL, NULL, process_fork, &g_array_index(hooks, LttvTraceHook, 7)); - lttv_trace_find_hook(ts->parent.t, "core", "process_exit", NULL, NULL, - NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 8)); -#endif //0 /* Add these hooks to each event_by_id hooks list */ - nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) + - ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = ts->parent.tracefiles->len; for(j = 0 ; j < nb_tracefile ; j++) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]); + tfs = + LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles, + LttvTracefileContext, j)); for(k = 0 ; k < hooks->len ; k++) { - hook = g_array_index(hooks, LttvTraceHook, k); - lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id, - hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k), LTTV_PRIO_STATE); + hook = &g_array_index(hooks, LttvTraceHook, k); + for(l=0;lfac_list->len;l++) { + thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l); + lttv_hooks_add( + lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id), + thf->h, + &g_array_index(hooks, LttvTraceHook, k), + LTTV_PRIO_STATE); + } } } lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val); @@ -1181,7 +1294,7 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self) { LttvTraceset *traceset = self->parent.ts; - guint i, j, k, nb_trace, nb_tracefile; + guint i, j, k, l, nb_trace, nb_tracefile; LttvTraceState *ts; @@ -1189,7 +1302,9 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self) GArray *hooks; - LttvTraceHook hook; + LttvTraceHook *hook; + + LttvTraceHookByFacility *thf; LttvAttributeValue val; @@ -1201,17 +1316,24 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self) /* Remove these hooks from each event_by_id hooks list */ - nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) + - ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = ts->parent.tracefiles->len; for(j = 0 ; j < nb_tracefile ; j++) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]); + tfs = + LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles, + LttvTracefileContext, j)); for(k = 0 ; k < hooks->len ; k++) { - hook = g_array_index(hooks, LttvTraceHook, k); - lttv_hooks_remove_data( - lttv_hooks_by_id_find(tfs->parent.event_by_id, - hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k)); + hook = &g_array_index(hooks, LttvTraceHook, k); + for(l=0;lfac_list->len;l++) { + thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l); + + lttv_hooks_remove_data( + lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id), + thf->h, + &g_array_index(hooks, LttvTraceHook, k)); + } + lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k)); } } g_array_free(hooks, TRUE); @@ -1219,6 +1341,50 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self) } +static gboolean state_save_event_hook(void *hook_data, void *call_data) +{ + guint *event_count = (guint*)hook_data; + + /* Only save at LTTV_STATE_SAVE_INTERVAL */ + if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL)) + return FALSE; + else + event_count = 0; + + LttvTracefileState *self = (LttvTracefileState *)call_data; + + LttvTracefileState *tfcs; + + LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context); + + LttEventPosition *ep; + + guint i; + + LttTracefile *tf; + + LttvAttribute *saved_states_tree, *saved_state_tree; + + LttvAttributeValue value; + + saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, + LTTV_STATE_SAVED_STATES); + saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + value = lttv_attribute_add(saved_states_tree, + lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT); + *(value.v_gobject) = (GObject *)saved_state_tree; + value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME); + *(value.v_time) = self->parent.timestamp; + lttv_state_save(tcs, saved_state_tree); + g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec, + self->parent.timestamp.tv_nsec); + + *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp; + + return FALSE; +} + +#if 0 static gboolean block_start(void *hook_data, void *call_data) { LttvTracefileState *self = (LttvTracefileState *)call_data; @@ -1238,14 +1404,16 @@ static gboolean block_start(void *hook_data, void *call_data) LttvAttributeValue value; ep = ltt_event_position_new(); - nb_tracefile = ltt_trace_control_tracefile_number(tcs->parent.t) + - ltt_trace_per_cpu_tracefile_number(tcs->parent.t); + + nb_tracefile = tcs->parent.tracefiles->len; /* Count the number of events added since the last block end in any tracefile. */ for(i = 0 ; i < nb_tracefile ; i++) { - tfcs = (LttvTracefileState *)tcs->parent.tracefiles[i]; + tfcs = + LTTV_TRACEFILE_STATE(&g_array_index(tcs->parent.tracefiles, + LttvTracefileContext, i)); ltt_event_position(tfcs->parent.e, ep); ltt_event_position_get(ep, &nb_block, &nb_event, &tf); tcs->nb_event += nb_event - tfcs->saved_position; @@ -1270,8 +1438,9 @@ static gboolean block_start(void *hook_data, void *call_data) *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp; return FALSE; } +#endif //0 - +#if 0 static gboolean block_end(void *hook_data, void *call_data) { LttvTracefileState *self = (LttvTracefileState *)call_data; @@ -1294,8 +1463,8 @@ static gboolean block_end(void *hook_data, void *call_data) return FALSE; } - - +#endif //0 +#if 0 void lttv_state_save_add_event_hooks(LttvTracesetState *self) { LttvTraceset *traceset = self->parent.ts; @@ -1311,20 +1480,56 @@ void lttv_state_save_add_event_hooks(LttvTracesetState *self) nb_trace = lttv_traceset_number(traceset); for(i = 0 ; i < nb_trace ; i++) { ts = (LttvTraceState *)self->parent.traces[i]; + lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL, NULL, NULL, block_start, &hook_start); lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, NULL, NULL, block_end, &hook_end); - nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) + - ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = ts->parent.tracefiles->len; for(j = 0 ; j < nb_tracefile ; j++) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]); + tfs = + LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles, + LttvTracefileContext, j)); lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id, - hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE); + hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE); lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id, - hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE); + hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE); + } + } +} +#endif //0 + +void lttv_state_save_add_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, nb_trace, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + + ts = (LttvTraceState *)self->parent.traces[i]; + nb_tracefile = ts->parent.tracefiles->len; + + guint *event_count = g_new(guint, 1); + *event_count = 0; + + for(j = 0 ; j < nb_tracefile ; j++) { + tfs = + LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles, + LttvTracefileContext, j)); + lttv_hooks_add(tfs->parent.event, + state_save_event_hook, + event_count, + LTTV_PRIO_STATE); + } } } @@ -1339,6 +1544,7 @@ gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data) } +#if 0 void lttv_state_save_remove_event_hooks(LttvTracesetState *self) { LttvTraceset *traceset = self->parent.ts; @@ -1354,17 +1560,19 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self) nb_trace = lttv_traceset_number(traceset); for(i = 0 ; i < nb_trace ; i++) { ts = LTTV_TRACE_STATE(self->parent.traces[i]); + lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL, NULL, NULL, block_start, &hook_start); lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, NULL, NULL, block_end, &hook_end); - nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) + - ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = ts->parent.tracefiles->len; for(j = 0 ; j < nb_tracefile ; j++) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]); + tfs = + LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles, + LttvTracefileContext, j)); lttv_hooks_remove_data(lttv_hooks_by_id_find( tfs->parent.event_by_id, hook_start.id), hook_start.h, NULL); lttv_hooks_remove_data(lttv_hooks_by_id_find( @@ -1372,6 +1580,38 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self) } } } +#endif //0 + +void lttv_state_save_remove_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, nb_trace, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + + ts = (LttvTraceState *)self->parent.traces[i]; + nb_tracefile = ts->parent.tracefiles->len; + + guint *event_count; + + for(j = 0 ; j < nb_tracefile ; j++) { + tfs = + LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles, + LttvTracefileContext, j)); + event_count = lttv_hooks_remove(tfs->parent.event, + state_save_event_hook); + g_free(event_count); + + } + } +} gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data) { @@ -1628,6 +1868,34 @@ static void module_init() LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables"); LTTV_STATE_TRACE_STATE_USE_COUNT = g_quark_from_string("trace_state_use_count"); + + + LTT_FACILITY_KERNEL = g_quark_from_string("kernel"); + LTT_FACILITY_PROCESS = g_quark_from_string("process"); + + + LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry"); + LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit"); + LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry"); + LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit"); + LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry"); + LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit"); + LTT_EVENT_SCHEDCHANGE = g_quark_from_string("schedchange"); + LTT_EVENT_FORK = g_quark_from_string("fork"); + LTT_EVENT_EXIT = g_quark_from_string("exit"); + LTT_EVENT_FREE = g_quark_from_string("free"); + + + LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id"); + LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id"); + LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id"); + LTT_FIELD_OUT = g_quark_from_string("out"); + LTT_FIELD_IN = g_quark_from_string("in"); + LTT_FIELD_OUT_STATE = g_quark_from_string("out_state"); + LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid"); + LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid"); + LTT_FIELD_PID = g_quark_from_string("pid"); + } static void module_destroy() diff --git a/ltt/branches/poly/lttv/lttv/state.h b/ltt/branches/poly/lttv/lttv/state.h index f3499937..f8f7a577 100644 --- a/ltt/branches/poly/lttv/lttv/state.h +++ b/ltt/branches/poly/lttv/lttv/state.h @@ -51,6 +51,43 @@ /* Priority of state hooks */ #define LTTV_PRIO_STATE 25 +#define LTTV_STATE_SAVE_INTERVAL 50000 + +/* Facilities Quarks */ + +extern GQuark + LTT_FACILITY_KERNEL, + LTT_FACILITY_PROCESS; + +/* Events Quarks */ + +extern GQuark + LTT_EVENT_SYSCALL_ENTRY, + LTT_EVENT_SYSCALL_EXIT, + LTT_EVENT_TRAP_ENTRY, + LTT_EVENT_TRAP_EXIT, + LTT_EVENT_IRQ_ENTRY, + LTT_EVENT_IRQ_EXIT, + LTT_EVENT_SCHEDCHANGE, + LTT_EVENT_FORK, + LTT_EVENT_EXIT, + LTT_EVENT_FREE; + +/* Fields Quarks */ + +extern GQuark + LTT_FIELD_SYSCALL_ID, + LTT_FIELD_TRAP_ID, + LTT_FIELD_IRQ_ID, + LTT_FIELD_OUT, + LTT_FIELD_IN, + LTT_FIELD_OUT_STATE, + LTT_FIELD_PARENT_PID, + LTT_FIELD_CHILD_PID, + LTT_FIELD_PID; + +extern GQuark LTT_EVENT_SYSCALL_ENTRY; + typedef struct _LttvTracesetState LttvTracesetState; typedef struct _LttvTracesetStateClass LttvTracesetStateClass; @@ -238,7 +275,7 @@ struct _LttvTracefileState { LttvProcessState *process; GQuark cpu_name; - guint saved_position; +// guint saved_position; }; struct _LttvTracefileStateClass { diff --git a/ltt/branches/poly/lttv/lttv/stats.c b/ltt/branches/poly/lttv/lttv/stats.c index 4f476d93..330166ba 100644 --- a/ltt/branches/poly/lttv/lttv/stats.c +++ b/ltt/branches/poly/lttv/lttv/stats.c @@ -110,11 +110,11 @@ init(LttvTracesetStats *self, LttvTraceset *ts) g_assert(lttv_attribute_get_number(tcs->stats) == 0); } - nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + - ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = tc->tracefiles->len; for(j = 0 ; j < nb_tracefile ; j++) { - tfcs = LTTV_TRACEFILE_STATS(tc->tracefiles[j]); + tfcs = LTTV_TRACEFILE_STATS(&g_array_index(tc->tracefiles, + LttvTracefileContext, j)); tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats, tfcs->parent.cpu_name); find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN, @@ -174,11 +174,11 @@ fini(LttvTracesetStats *self) } tcs->stats = NULL; - nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + - ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = tc->tracefiles->len; for(j = 0 ; j < nb_tracefile ; j++) { - tfc = tc->tracefiles[j]; + tfc = &g_array_index(tc->tracefiles, + LttvTracefileContext, j); tfcs = (LttvTracefileStats *)tfc; tfcs->stats = NULL; tfcs->current_events_tree = NULL; @@ -518,17 +518,21 @@ gboolean after_irq_exit(void *hook_data, void *call_data) gboolean before_schedchange(void *hook_data, void *call_data) { - LttvTraceHook *h = (LttvTraceHook *)hook_data; - LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data; + LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf); + + LttvTraceHookByFacility *thf = + lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, + ltt_event_facility_id(e)); + guint pid_in, pid_out, state_out; LttvProcessState *process; - pid_in = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f1); - pid_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f2); - state_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f3); + pid_out = ltt_event_get_unsigned(e, thf->f1); + pid_in = ltt_event_get_unsigned(e, thf->f2); + state_out = ltt_event_get_unsigned(e, thf->f3); /* compute the time for the process to schedule out */ @@ -563,11 +567,17 @@ gboolean process_exit(void *hook_data, void *call_data) return FALSE; } +gboolean process_free(void *hook_data, void *call_data) +{ + return FALSE; +} gboolean every_event(void *hook_data, void *call_data) { LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data; + LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf); + LttvAttributeValue v; /* The current branch corresponds to the tracefile/process/interrupt state. @@ -576,8 +586,7 @@ gboolean every_event(void *hook_data, void *call_data) event type and is used as name. */ lttv_attribute_find(tfcs->current_event_types_tree, - ((LttvTraceState *)(tfcs->parent.parent.t_context))-> - eventtype_names[ltt_event_eventtype_id(tfcs->parent.parent.e)], + ltt_eventtype_name(ltt_event_eventtype(e)), LTTV_UINT, &v); (*(v.v_uint))++; return FALSE; @@ -732,7 +741,7 @@ void lttv_stats_add_event_hooks(LttvTracesetStats *self) { LttvTraceset *traceset = self->parent.parent.ts; - guint i, j, k, nb_trace, nb_tracefile; + guint i, j, k, l, nb_trace, nb_tracefile; LttFacility *f; @@ -746,7 +755,9 @@ void lttv_stats_add_event_hooks(LttvTracesetStats *self) GArray *hooks, *before_hooks, *after_hooks; - LttvTraceHook hook; + LttvTraceHook *hook; + + LttvTraceHookByFacility *thf; LttvAttributeValue val; @@ -757,91 +768,136 @@ void lttv_stats_add_event_hooks(LttvTracesetStats *self) /* Find the eventtype id for the following events and register the associated by id hooks. */ - hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); + hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 7); g_array_set_size(hooks, 7); - lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry", - "syscall_id", NULL, NULL, before_syscall_entry, + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY, + LTT_FIELD_SYSCALL_ID, 0, 0, + before_syscall_entry, &g_array_index(hooks, LttvTraceHook, 0)); - lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL, - NULL, NULL, before_syscall_exit, + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT, + 0, 0, 0, + before_syscall_exit, &g_array_index(hooks, LttvTraceHook, 1)); - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id", - NULL, NULL, before_trap_entry, + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY, + LTT_FIELD_TRAP_ID, 0, 0, + before_trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL, - NULL, before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id", - NULL, NULL, before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL, - NULL, before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "schedchange", "in", - "out", "out_state", before_schedchange, - &g_array_index(hooks, LttvTraceHook, 6)); + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT, + 0, 0, 0, + before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); + + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY, + LTT_FIELD_IRQ_ID, 0, 0, + before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); + + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT, + 0, 0, 0, + before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); + + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE, + LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE, + before_schedchange, + &g_array_index(hooks, LttvTraceHook, 6)); before_hooks = hooks; - hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); - g_array_set_size(hooks, 8); + hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 9); + g_array_set_size(hooks, 9); - lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry", - "syscall_id", NULL, NULL, after_syscall_entry, + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY, + LTT_FIELD_SYSCALL_ID, 0, 0, + after_syscall_entry, &g_array_index(hooks, LttvTraceHook, 0)); - lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL, - NULL, NULL, after_syscall_exit, + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT, + 0, 0, 0, + after_syscall_exit, &g_array_index(hooks, LttvTraceHook, 1)); - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id", - NULL, NULL, after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY, + LTT_FIELD_TRAP_ID, 0, 0, + after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); + + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT, + 0, 0, 0, + after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL, - NULL, after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY, + LTT_FIELD_IRQ_ID, 0, 0, + after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id", - NULL, NULL, after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT, + 0, 0, 0, + after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL, - NULL, after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); - lttv_trace_find_hook(ts->parent.parent.t, "core", "process_fork", - "child_pid", NULL, NULL, process_fork, + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_PROCESS, LTT_EVENT_FORK, + LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0, + process_fork, &g_array_index(hooks, LttvTraceHook, 6)); - lttv_trace_find_hook(ts->parent.parent.t, "core", "process_exit", NULL, - NULL, NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 7)); + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_PROCESS, LTT_EVENT_EXIT, + LTT_FIELD_PID, 0, 0, + process_exit, &g_array_index(hooks, LttvTraceHook, 7)); + + lttv_trace_find_hook(ts->parent.parent.t, + LTT_FACILITY_PROCESS, LTT_EVENT_FREE, + LTT_FIELD_PID, 0, 0, + process_free, &g_array_index(hooks, LttvTraceHook, 7)); + after_hooks = hooks; /* Add these hooks to each event_by_id hooks list */ - nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) + - ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t); + nb_tracefile = ts->parent.parent.tracefiles->len; for(j = 0 ; j < nb_tracefile ; j++) { - tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]); + tfs = LTTV_TRACEFILE_STATS(&g_array_index(ts->parent.parent.tracefiles, + LttvTracefileContext, j)); lttv_hooks_add(tfs->parent.parent.event, every_event, NULL, LTTV_PRIO_DEFAULT); for(k = 0 ; k < before_hooks->len ; k++) { - hook = g_array_index(before_hooks, LttvTraceHook, k); - lttv_hooks_add(lttv_hooks_by_id_find( - tfs->parent.parent.event_by_id, - hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k), - LTTV_PRIO_STATS_BEFORE_STATE); + hook = &g_array_index(before_hooks, LttvTraceHook, k); + for(l = 0; lfac_list->len;l++) { + thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l); + lttv_hooks_add( + lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id), + thf->h, + &g_array_index(before_hooks, LttvTraceHook, k), + LTTV_PRIO_STATS_BEFORE_STATE); + } } for(k = 0 ; k < after_hooks->len ; k++) { - hook = g_array_index(after_hooks, LttvTraceHook, k); - lttv_hooks_add(lttv_hooks_by_id_find( - tfs->parent.parent.event_by_id, - hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k), - LTTV_PRIO_STATS_AFTER_STATE); + hook = &g_array_index(after_hooks, LttvTraceHook, k); + for(l = 0; lfac_list->len;l++) { + thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l); + lttv_hooks_add( + lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id), + thf->h, + &g_array_index(after_hooks, LttvTraceHook, k), + LTTV_PRIO_STATS_AFTER_STATE); + } } } lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS, @@ -867,7 +923,7 @@ void lttv_stats_remove_event_hooks(LttvTracesetStats *self) { LttvTraceset *traceset = self->parent.parent.ts; - guint i, j, k, nb_trace, nb_tracefile; + guint i, j, k, l, nb_trace, nb_tracefile; LttvTraceStats *ts; @@ -877,7 +933,9 @@ void lttv_stats_remove_event_hooks(LttvTracesetStats *self) GArray *before_hooks, *after_hooks; - LttvTraceHook hook; + LttvTraceHook *hook; + + LttvTraceHookByFacility *thf; LttvAttributeValue val; @@ -893,25 +951,33 @@ void lttv_stats_remove_event_hooks(LttvTracesetStats *self) /* Remove these hooks from each event_by_id hooks list */ - nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) + - ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t); + nb_tracefile = ts->parent.parent.tracefiles->len; for(j = 0 ; j < nb_tracefile ; j++) { - tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]); + tfs = LTTV_TRACEFILE_STATS(&g_array_index(ts->parent.parent.tracefiles, + LttvTracefileContext, j)); lttv_hooks_remove_data(tfs->parent.parent.event, every_event, NULL); for(k = 0 ; k < before_hooks->len ; k++) { - hook = g_array_index(before_hooks, LttvTraceHook, k); - lttv_hooks_remove_data( - lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, - hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k)); + hook = &g_array_index(before_hooks, LttvTraceHook, k); + for(l = 0 ; l < hook->fac_list->len ; l++) { + thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l); + lttv_hooks_remove_data( + lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id), + thf->h, + &g_array_index(before_hooks, LttvTraceHook, k)); + } } for(k = 0 ; k < after_hooks->len ; k++) { - hook = g_array_index(after_hooks, LttvTraceHook, k); - lttv_hooks_remove_data( - lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, - hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k)); + hook = &g_array_index(after_hooks, LttvTraceHook, k); + for(l = 0 ; l < hook->fac_list->len ; l++) { + thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l); + lttv_hooks_remove_data( + lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id), + thf->h, + &g_array_index(after_hooks, LttvTraceHook, k)); + } } } g_debug("lttv_stats_remove_event_hooks()"); diff --git a/ltt/branches/poly/lttv/lttv/tracecontext.c b/ltt/branches/poly/lttv/lttv/tracecontext.c index 6179f95e..30a30ba3 100644 --- a/ltt/branches/poly/lttv/lttv/tracecontext.c +++ b/ltt/branches/poly/lttv/lttv/tracecontext.c @@ -145,6 +145,25 @@ static void lttv_traceset_context_compute_time_span( } } +static void init_tracefile_context(LttTracefile *tracefile, + LttvTraceContext *tc) +{ + LttvTracefileContext *tfc; + LttvTracesetContext *tsc = tc->ts_context; + + tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(tsc)->new_tracefile_context(tsc); + + tfc->index = tc->tracefiles->len; + tc->tracefiles = g_array_append_val(tc->tracefiles, tfc); + + tfc->tf = tracefile; + + tfc->t_context = tc; + tfc->event = lttv_hooks_new(); + tfc->event_by_id = lttv_hooks_by_id_new(); + tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); +} + static void init(LttvTracesetContext *self, LttvTraceset *ts) @@ -153,9 +172,9 @@ init(LttvTracesetContext *self, LttvTraceset *ts) LttvTraceContext *tc; - LttvTracefileContext *tfc; + GData *tracefiles_groups; - LttTime null_time = {0, 0}; + struct compute_tracefile_group_args args; nb_trace = lttv_traceset_number(ts); self->ts = ts; @@ -172,6 +191,17 @@ init(LttvTracesetContext *self, LttvTraceset *ts) tc->t = lttv_trace(tc->vt); tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); tc->t_a = lttv_trace_attribute(tc->vt); + + tracefiles_groups = ltt_trace_get_tracefiles_groups(tc->t); + + args.func = (ForEachTraceFileFunc)init_tracefile_context; + args.func_args = tc; + + g_datalist_foreach(&tracefiles_groups, + (GDataForeachFunc)compute_tracefile_group, + &args); + +#if 0 nb_control = ltt_trace_control_tracefile_number(tc->t); nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); nb_tracefile = nb_control + nb_per_cpu; @@ -190,15 +220,18 @@ init(LttvTracesetContext *self, LttvTraceset *ts) tfc->control = FALSE; tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control); } + tfc->t_context = tc; tfc->e = ltt_event_new(); tfc->event = lttv_hooks_new(); tfc->event_by_id = lttv_hooks_by_id_new(); tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); } +#endif //0 + } self->pqueue = g_tree_new(compare_tracefile); - lttv_process_traceset_seek_time(self, null_time); + lttv_process_traceset_seek_time(self, ltt_time_zero); lttv_traceset_context_compute_time_span(self, &self->time_span); } @@ -226,18 +259,16 @@ void fini(LttvTracesetContext *self) g_object_unref(tc->a); - nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + - ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = tc->tracefiles->len; for(j = 0 ; j < nb_tracefile ; j++) { - tfc = tc->tracefiles[j]; - ltt_event_destroy(tfc->e); + tfc = &g_array_index(tc->tracefiles, LttvTracefileContext, j); lttv_hooks_destroy(tfc->event); lttv_hooks_by_id_destroy(tfc->event_by_id); g_object_unref(tfc->a); g_object_unref(tfc); } - g_free(tc->tracefiles); + g_array_free(tc->tracefiles, TRUE); g_object_unref(tc); } g_free(self->traces); @@ -313,11 +344,11 @@ void lttv_trace_context_add_hooks(LttvTraceContext *self, LttvTracefileContext *tfc; lttv_hooks_call(before_trace, self); - nb_tracefile = ltt_trace_control_tracefile_number(self->t) + - ltt_trace_per_cpu_tracefile_number(self->t); + + nb_tracefile = self->tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { - tfc = self->tracefiles[i]; + tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i); lttv_tracefile_context_add_hooks(tfc, before_tracefile, event, @@ -337,11 +368,10 @@ void lttv_trace_context_remove_hooks(LttvTraceContext *self, LttvTracefileContext *tfc; - nb_tracefile = ltt_trace_control_tracefile_number(self->t) + - ltt_trace_per_cpu_tracefile_number(self->t); + nb_tracefile = self->tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { - tfc = self->tracefiles[i]; + tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i); lttv_tracefile_context_remove_hooks(tfc, after_tracefile, event, @@ -605,17 +635,16 @@ void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext *self) LttvTracefileContext *tfc; - nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + - ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = tc->tracefiles->len; for(iter_tf = 0 ; iter_tf < nb_tracefile ; iter_tf++) { - tfc = tc->tracefiles[iter_tf]; + tfc = &g_array_index(tc->tracefiles, LttvTracefileContext, iter_tf); { /* each tracefile */ //ltt_tracefile_copy(tfc->tf_sync_data, tfc->tf); LttEventPosition *ep = ltt_event_position_new(); - ltt_event_position(tfc->e, ep); + ltt_event_position(ltt_tracefile_get_event(tfc->tf), ep); ltt_tracefile_seek_position(tfc->tf, ep); g_free(ep); @@ -658,6 +687,8 @@ guint lttv_process_traceset_middle(LttvTracesetContext *self, LttvTracefileContext *tfc; + LttEvent *e; + unsigned count = 0; gboolean last_ret = FALSE; /* return value of the last hook list called */ @@ -699,13 +730,14 @@ guint lttv_process_traceset_middle(LttvTracesetContext *self, g_tree_remove(pqueue, tfc); count++; - - id = ltt_event_eventtype_id(tfc->e); + + e = ltt_tracefile_get_event(tfc->tf); + id = ltt_event_eventtype_id(e); last_ret = lttv_hooks_call_merge(tfc->event, tfc, lttv_hooks_by_id_get(tfc->event_by_id, id), tfc); - if(likely(ltt_tracefile_read(tfc->tf, tfc->e) != NULL)) { - tfc->timestamp = ltt_event_time(tfc->e); + if(likely(!ltt_tracefile_read(tfc->tf))) { + tfc->timestamp = ltt_event_time(e); g_tree_insert(pqueue, tfc, tfc); } } @@ -733,21 +765,21 @@ void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start) { guint i, nb_tracefile; + gint ret; + LttvTracefileContext *tfc; GTree *pqueue = self->ts_context->pqueue; - nb_tracefile = ltt_trace_control_tracefile_number(self->t) + - ltt_trace_per_cpu_tracefile_number(self->t); + nb_tracefile = self->tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { - tfc = self->tracefiles[i]; - ltt_tracefile_seek_time(tfc->tf, start); + tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i); + ret = ltt_tracefile_seek_time(tfc->tf, start); + if(ret) g_error("error in lttv_process_trace_seek_time seek"); g_tree_remove(pqueue, tfc); - if(likely(ltt_tracefile_read(tfc->tf, tfc->e) != NULL)) { - tfc->timestamp = ltt_event_time(tfc->e); - g_tree_insert(pqueue, tfc, tfc); - } + tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf)); + g_tree_insert(pqueue, tfc, tfc); } } @@ -775,10 +807,8 @@ gboolean lttv_process_tracefile_seek_position(LttvTracefileContext *self, ltt_tracefile_seek_position(tfc->tf, pos); g_tree_remove(pqueue, tfc); - if(likely(ltt_tracefile_read(tfc->tf, tfc->e) != NULL)) { - tfc->timestamp = ltt_event_time(tfc->e); - g_tree_insert(pqueue, tfc, tfc); - } + tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf)); + g_tree_insert(pqueue, tfc, tfc); return TRUE; } @@ -790,14 +820,13 @@ gboolean lttv_process_trace_seek_position(LttvTraceContext *self, LttvTracefileContext *tfc; - nb_tracefile = ltt_trace_control_tracefile_number(self->t) + - ltt_trace_per_cpu_tracefile_number(self->t); + nb_tracefile = self->tracefiles->len; if(nb_tracefile != pos->nb_tracefile) return FALSE; /* Error */ for(i = 0 ; i < nb_tracefile ; i++) { - tfc = self->tracefiles[i]; + tfc = &g_array_index(self->tracefiles, LttvTracefileContext, i); lttv_process_tracefile_seek_position(tfc, pos->tf_pos[i]); } @@ -830,7 +859,7 @@ gboolean lttv_process_traceset_seek_position(LttvTracesetContext *self, static LttField * -find_field(LttEventType *et, const char *field) +find_field(LttEventType *et, const GQuark field) { LttType *t; @@ -838,44 +867,138 @@ find_field(LttEventType *et, const char *field) guint i, nb; - char *name; - - if(field == NULL) return NULL; + GQuark name; + /* Field is unset */ + if(field == 0) return NULL; + f = ltt_eventtype_field(et); t = ltt_eventtype_type(et); g_assert(ltt_type_class(t) == LTT_STRUCT); nb = ltt_type_member_number(t); for(i = 0 ; i < nb ; i++) { ltt_type_member_type(t, i, &name); - if(strcmp(name, field) == 0) break; + if(name == field) break; } g_assert(i < nb); return ltt_field_member(f, i); } +LttvTraceHookByFacility *lttv_trace_hook_get_fac(LttvTraceHook *th, + guint facility_id) +{ + return &g_array_index(th->fac_index, LttvTraceHookByFacility, facility_id); +} + +/* Get the first facility corresponding to the name. As the types must be + * compatible, it is relevant to use the field name and sizes of the first + * facility to create data structures and assume the data will be compatible + * thorough the trace */ +LttvTraceHookByFacility *lttv_trace_hook_get_first(LttvTraceHook *th) +{ + g_assert(th->fac_list->len > 0); + return g_array_index(th->fac_list, LttvTraceHookByFacility*, 0); +} + -void -lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type, - char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th) +/* Returns 0 on success, -1 if fails. */ +gint +lttv_trace_find_hook(LttTrace *t, GQuark facility, GQuark event, + GQuark field1, GQuark field2, GQuark field3, LttvHook h, LttvTraceHook *th) { LttFacility *f; - LttEventType *et; + LttEventType *et, *first_et; + + GArray *facilities; + + guint i, fac_id; - guint nb, pos; + LttvTraceHookByFacility *thf, *first_thf; - nb = ltt_trace_facility_find(t, facility, &pos); - if(unlikely(nb < 1)) g_error("No %s facility", facility); - f = ltt_trace_facility_get(t, pos); - et = ltt_facility_eventtype_get_by_name(f, event_type); - if(unlikely(et == NULL)) g_error("Event %s does not exist", event_type); + facilities = ltt_trace_facility_get_by_name(t, facility); + + if(unlikely(facilities == NULL)) goto facility_error; + + th->fac_index = g_array_sized_new(FALSE, TRUE, + sizeof(LttvTraceHookByFacility), + NUM_FACILITIES); + th->fac_index = g_array_set_size(th->fac_index, NUM_FACILITIES); - th->h = h; - th->id = ltt_eventtype_id(et); - th->f1 = find_field(et, field1); - th->f2 = find_field(et, field2); - th->f3 = find_field(et, field3); + th->fac_list = g_array_sized_new(FALSE, TRUE, + sizeof(LttvTraceHookByFacility*), + facilities->len); + th->fac_list = g_array_set_size(th->fac_list, facilities->len); + + fac_id = g_array_index(facilities, guint, 0); + f = ltt_trace_get_facility_by_num(t, fac_id); + + et = ltt_facility_eventtype_get_by_name(f, ltt_eventtype_name(et)); + if(unlikely(et == NULL)) goto event_error; + + thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id); + g_array_index(th->fac_list, LttvTraceHookByFacility*, 0) + = thf; + thf->h = h; + thf->id = ltt_eventtype_id(et); + thf->f1 = find_field(et, field1); + thf->f2 = find_field(et, field2); + thf->f3 = find_field(et, field3); + + first_thf = thf; + + /* Check for type compatibility too */ + for(i=1;ilen;i++) { + fac_id = g_array_index(facilities, guint, i); + f = ltt_trace_get_facility_by_num(t, fac_id); + + et = ltt_facility_eventtype_get_by_name(f, ltt_eventtype_name(et)); + if(unlikely(et == NULL)) goto event_error; + + thf = &g_array_index(th->fac_index, LttvTraceHookByFacility, fac_id); + g_array_index(th->fac_list, LttvTraceHookByFacility*, i) + = thf; + thf->h = h; + thf->id = ltt_eventtype_id(et); + thf->f1 = find_field(et, field1); + if(check_fields_compatibility(first_et, et, + first_thf->f1, thf->f1)) + goto type_error; + + thf->f2 = find_field(et, field2); + if(check_fields_compatibility(first_et, et, + first_thf->f2, thf->f2)) + goto type_error; + + thf->f3 = find_field(et, field3); + if(check_fields_compatibility(first_et, et, + first_thf->f3, thf->f3)) + goto type_error; + } + + return 0; + +type_error: + goto free; +event_error: + g_error("Event type %s does not exist", + g_quark_to_string(ltt_eventtype_name(et))); + goto free; +facility_error: + g_error("No %s facility", g_quark_to_string(facility)); + goto free; +free: + g_array_free(th->fac_index, TRUE); + g_array_free(th->fac_list, TRUE); + th->fac_index = NULL; + th->fac_list = NULL; + return -1; +} + +void lttv_trace_hook_destroy(LttvTraceHook *th) +{ + g_array_free(th->fac_index, TRUE); + g_array_free(th->fac_list, TRUE); } @@ -904,14 +1027,15 @@ void lttv_traceset_context_position_save(const LttvTracesetContext *self, for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) { tc = self->traces[iter_trace]; - pos->t_pos[iter_trace].nb_tracefile = nb_tracefile = - ltt_trace_control_tracefile_number(tc->t) + - ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = tc->tracefiles->len; + pos->t_pos[iter_trace].nb_tracefile = nb_tracefile; + pos->t_pos[iter_trace].tf_pos = g_new(LttEventPosition*, nb_tracefile); for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) { - tfc = tc->tracefiles[iter_tracefile]; - event = tfc->e; + tfc = &g_array_index(tc->tracefiles, LttvTracefileContext, + iter_tracefile); + event = ltt_tracefile_get_event(tfc->tf); if(event!=NULL) { pos->t_pos[iter_trace].tf_pos[iter_tracefile] = ltt_event_position_new(); @@ -958,8 +1082,11 @@ void lttv_traceset_context_position_copy(LttvTracesetContextPosition *dest, for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) { - nb_tracefile = dest->t_pos[iter_trace].nb_tracefile = - src->t_pos[iter_trace].nb_tracefile; + nb_tracefile = src->t_pos[iter_trace].nb_tracefile; + + dest->t_pos[iter_trace].nb_tracefile = nb_tracefile; + + dest->t_pos[iter_trace].tf_pos = g_new(LttEventPosition*, nb_tracefile); for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) { dest->t_pos[iter_trace].tf_pos[iter_tracefile] = @@ -996,16 +1123,16 @@ gint lttv_traceset_context_ctx_pos_compare(const LttvTracesetContext *self, for(iter_trace = 0 ; iter_trace < nb_trace ; iter_trace++) { tc = self->traces[iter_trace]; - nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + - ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = tc->tracefiles->len; if(unlikely(pos->t_pos[iter_trace].nb_tracefile != nb_tracefile)) g_error("lttv_traceset_context_ctx_pos_compare : nb_tracefile does not match."); for(iter_tracefile = 0; iter_tracefile < nb_tracefile; iter_tracefile++) { - tfc = tc->tracefiles[iter_tracefile]; - event = tfc->e; - ret = ltt_event_event_position_compare(event, + tfc = &g_array_index(tc->tracefiles, LttvTracefileContext, + iter_tracefile); + event = ltt_tracefile_get_event(tfc->tf); + ret = ltt_event_position_compare((LttEventPosition*)event, pos->t_pos[iter_trace].tf_pos[iter_tracefile]); if(ret != 0) return ret; diff --git a/ltt/branches/poly/lttv/lttv/tracecontext.h b/ltt/branches/poly/lttv/lttv/tracecontext.h index dc652e25..6df7e6fe 100644 --- a/ltt/branches/poly/lttv/lttv/tracecontext.h +++ b/ltt/branches/poly/lttv/lttv/tracecontext.h @@ -135,7 +135,8 @@ struct _LttvTraceContext { guint index; /* in ts_context->traces */ LttTrace *t; LttvTrace *vt; - LttvTracefileContext **tracefiles; + //LttvTracefileContext **tracefiles; + GArray *tracefiles; LttvAttribute *a; LttvAttribute *t_a; }; @@ -157,10 +158,10 @@ struct _LttvTracefileContext { GObject parent; LttvTraceContext *t_context; - gboolean control; + // gboolean control; guint index; /* in ts_context->tracefiles */ LttTracefile *tf; - LttEvent *e; + // LttEvent *e; LttvHooks *event; LttvHooksById *event_by_id; LttTime timestamp; @@ -265,14 +266,32 @@ void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *self, void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *self, unsigned i); +/* A LttvTraceHook has two arrays of LttvTraceHookByFacility, + * indexed by facility ID and a simple array used to walk all the hooks */ typedef struct _LttvTraceHook { + GArray *fac_index; + GArray *fac_list; +} LttvTraceHook; + +typedef struct _LttvTraceHookByFacility { LttvHook h; guint id; LttField *f1; LttField *f2; LttField *f3; -} LttvTraceHook; +} LttvTraceHookByFacility; + + +/* Get the first facility corresponding to the name. As the types must be + * compatible, it is relevant to use the field name and sizes of the first + * facility to create data structures and assume the data will be compatible + * thorough the trace */ +LttvTraceHookByFacility *lttv_trace_hook_get_first(LttvTraceHook *th); + +LttvTraceHookByFacility *lttv_trace_hook_get_fac( + LttvTraceHook *th, guint facility_id); +void lttv_trace_hook_destroy(LttvTraceHook *th); /* Search in the trace for the id of the named event type within the named facility. Then, find the three (if non null) named fields. All that @@ -281,8 +300,8 @@ typedef struct _LttvTraceHook { registering a hook using this structure as event data; it already contains the (up to three) needed fields handles. */ -void lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type, - char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th); +gint lttv_trace_find_hook(LttTrace *t, GQuark facility, GQuark event_type, + GQuark field1, GQuark field2, GQuark field3, LttvHook h, LttvTraceHook *th); LttvTracefileContext *lttv_traceset_context_get_current_tfc( LttvTracesetContext *self); -- 2.34.1