X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Fltt%2Ftracefile.c;h=afec19efb1e4dba7b36a492ee6a10d1c033d6c03;hb=3865ea0940b718a7832b813a790f287140233efc;hp=b78f4834b9d4748f9f332c5ec491921df36f0043;hpb=3aee1200b100fe8063661fd2d8eaa5fbbfc1977f;p=lttv.git diff --git a/ltt/branches/poly/ltt/tracefile.c b/ltt/branches/poly/ltt/tracefile.c index b78f4834..afec19ef 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, @@ -181,7 +176,7 @@ static void parser_characters (GMarkupParseContext __UNUSED__ *context, des->description = g_strdup(text); } #endif //0 -static inline LttFacility *ltt_trace_get_facility_by_num(LttTrace *t, +LttFacility *ltt_trace_get_facility_by_num(LttTrace *t, guint num) { g_assert(num < t->facilities_by_num->len); @@ -210,7 +205,7 @@ gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf) //open the file tf->name = g_quark_from_string(fileName); tf->trace = t; - tf->fd = g_open(fileName, O_RDONLY, 0); + tf->fd = open(fileName, O_RDONLY); if(tf->fd < 0){ g_warning("Unable to open input data file %s\n", fileName); goto end; @@ -232,11 +227,11 @@ gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf) /* Multiple of pages aligned head */ tf->buffer.head = mmap(0, sizeof(struct ltt_block_start_header), PROT_READ, MAP_PRIVATE, tf->fd, 0); - if(tf->buffer.head == NULL) { + if(tf->buffer.head == MAP_FAILED) { perror("Error in allocating memory for buffer of tracefile"); goto close_file; } - g_assert(((guint)tf->buffer.head & (8-1)) == 0); // make sure it's aligned. + g_assert( ( (guint)tf->buffer.head&(8-1) ) == 0); // make sure it's aligned. header = (struct ltt_block_start_header*)tf->buffer.head; @@ -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 @@ -267,7 +262,7 @@ gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf) unmap_file: munmap(tf->buffer.head, sizeof(struct ltt_block_start_header)); close_file: - g_close(tf->fd); + close(tf->fd); end: return -1; } @@ -351,7 +346,7 @@ void ltt_tracefile_close(LttTracefile *t) { if(t->buffer.head != NULL) munmap(t->buffer.head, t->buf_size); - g_close(t->fd); + close(t->fd); } @@ -542,6 +537,27 @@ int get_tracefile_name_number(const gchar *raw_name, } +GData **ltt_trace_get_tracefiles_groups(LttTrace *trace) +{ + return &trace->tracefiles; +} + + +void compute_tracefile_group(GQuark key_id, + GArray *group, + struct compute_tracefile_group_args *args) +{ + int i; + LttTracefile *tf; + + for(i=0; ilen; i++) { + tf = &g_array_index (group, LttTracefile, i); + if(tf->cpu_online) + args->func(tf, args->func_args); + } +} + + void ltt_tracefile_group_destroy(gpointer data) { GArray *group = (GArray *)data; @@ -574,20 +590,29 @@ gboolean ltt_tracefile_group_has_cpu_online(gpointer data) * GData : permits to access them using their tracefile group pathname. * i.e. access control/modules tracefile group by index : * "control/module". + * + * relative path is the path relative to the trace root + * root path is the full path * * 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) +static int open_tracefiles(LttTrace *trace, char *root_path, + char *relative_path) { DIR *dir = opendir(root_path); struct dirent *entry; struct stat stat_buf; int ret; + char path[PATH_MAX]; int path_len; char *path_ptr; + int rel_path_len; + char rel_path[PATH_MAX]; + char *rel_path_ptr; + if(dir == NULL) { perror(root_path); return ENOENT; @@ -599,11 +624,18 @@ static int open_tracefiles(LttTrace *trace, char *root_path, GData *tracefiles) path_len++; path_ptr = path + path_len; + strncpy(rel_path, relative_path, PATH_MAX-1); + rel_path_len = strlen(rel_path); + rel_path[rel_path_len] = '/'; + rel_path_len++; + rel_path_ptr = rel_path + rel_path_len; + while((entry = readdir(dir)) != NULL) { if(entry->d_name[0] == '.') continue; strncpy(path_ptr, entry->d_name, PATH_MAX - path_len); + strncpy(rel_path_ptr, entry->d_name, PATH_MAX - rel_path_len); ret = stat(path, &stat_buf); if(ret == -1) { @@ -616,7 +648,7 @@ static int open_tracefiles(LttTrace *trace, char *root_path, GData *tracefiles) if(S_ISDIR(stat_buf.st_mode)) { g_debug("Entering subdirectory...\n"); - ret = open_tracefiles(trace, path, tracefiles); + ret = open_tracefiles(trace, path, rel_path); if(ret < 0) continue; } else if(S_ISREG(stat_buf.st_mode)) { g_debug("Opening file.\n"); @@ -627,16 +659,19 @@ static int open_tracefiles(LttTrace *trace, char *root_path, GData *tracefiles) LttTracefile *tf; guint len; - if(get_tracefile_name_number(path, &name, &num)) + if(get_tracefile_name_number(rel_path, &name, &num)) continue; /* invalid name */ - - group = g_datalist_id_get_data(&tracefiles, name); + + g_debug("Tracefile name is %s and number is %u", + g_quark_to_string(name), num); + + group = g_datalist_id_get_data(&trace->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_id_set_data_full(&tracefiles, name, + g_datalist_id_set_data_full(&trace->tracefiles, name, group, ltt_tracefile_group_destroy); } /* Add the per cpu tracefile to the named group */ @@ -650,7 +685,7 @@ static int open_tracefiles(LttTrace *trace, char *root_path, GData *tracefiles) g_array_set_size(group, old_len); if(!ltt_tracefile_group_has_cpu_online(group)) - g_datalist_id_remove_data(&tracefiles, name); + g_datalist_id_remove_data(&trace->tracefiles, name); continue; /* error opening the tracefile : bad magic number ? */ } @@ -809,7 +844,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); @@ -820,7 +855,8 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) fac->trace = tf->trace; fac->exists = 1; - fac_ids = g_datalist_id_get_data(&tf->trace->facilities_by_name, fac->name); + fac_ids = g_datalist_id_get_data(&tf->trace->facilities_by_name, + fac->name); if(fac_ids == NULL) { fac_ids = g_array_sized_new (FALSE, TRUE, sizeof(guint), 1); g_datalist_id_set_data_full(&tf->trace->facilities_by_name, @@ -845,10 +881,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); @@ -910,7 +946,7 @@ LttTrace *ltt_trace_open(const gchar *pathname) /* Open all the tracefiles */ g_datalist_init(&t->tracefiles); - if(open_tracefiles(t, abs_path, t->tracefiles)) + if(open_tracefiles(t, abs_path, "")) goto open_error; /* Prepare the facilities containers : array and mapping */ @@ -926,6 +962,7 @@ LttTrace *ltt_trace_open(const gchar *pathname) group = g_datalist_id_get_data(&t->tracefiles, LTT_TRACEFILE_NAME_FACILITIES); if(group == NULL) { g_error("Trace %s has no facility tracefile", abs_path); + g_assert(0); goto facilities_error; } @@ -1302,6 +1339,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 @@ -1398,7 +1444,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 */ @@ -1436,16 +1482,18 @@ 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 */ + ltt_update_event_size(tf); + return 0; } @@ -1472,14 +1520,15 @@ static gint map_block(LttTracefile * tf, guint block_num) munmap(tf->buffer.head, tf->buf_size); /* Multiple of pages aligned head */ - tf->buffer.head = mmap(0, tf->block_size, PROT_READ, tf->fd, MAP_PRIVATE, + tf->buffer.head = mmap(0, tf->block_size, PROT_READ, MAP_PRIVATE, tf->fd, (off_t)tf->block_size * (off_t)block_num); - if(tf->buffer.head == NULL) { + if(tf->buffer.head == MAP_FAILED) { perror("Error in allocating memory for buffer of tracefile"); + g_assert(0); goto map_error; } - g_assert(((guint)tf->buffer.head) & (8-1) == 0); // make sure it's aligned. + g_assert( ( (guint)tf->buffer.head&(8-1) ) == 0); // make sure it's aligned. tf->buffer.index = block_num; @@ -1517,7 +1566,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; @@ -1526,13 +1575,17 @@ map_error: } -ssize_t ltt_get_event_size(LttTracefile *tf) +/* It will update the fields offsets too */ +void ltt_update_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)) { + LttFacility *f = ltt_trace_get_facility_by_num(tf->trace, + tf->event.facility_id); + + if(likely(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); @@ -1554,19 +1607,19 @@ ssize_t ltt_get_event_size(LttTracefile *tf) 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); + size = get_field_type_size(tf, event_type, + 0, 0, event_type->root_field, tf->event.data); } - - return size; + tf->event.data_size = size; + + return; + event_id_error: - return -1; + tf->event.data_size = 0; } @@ -1588,25 +1641,24 @@ 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; } pos = tf->event.data; - event_size = ltt_get_event_size(tf); - if(event_size < 0) goto error; + if(tf->event.data_size < 0) goto error; - pos += (size_t)event_size; + pos += (size_t)tf->event.data_size; - tf->event.offset = pos; + tf->event.offset = pos - tf->buffer.head; found: return ret; @@ -1834,135 +1886,138 @@ 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. + * check_fields_compatibility : Check for compatibility between two fields : + * do they use the same inner structure ? *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. + * event_type1 : event type + * event_type2 : event type + * field1 : field + * field2 : field + *Returns : 0 if identical + * 1 if not. ****************************************************************************/ -size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type, - off_t offset_root, off_t offset_parent, - LttField *field, void *data) +gint check_fields_compatibility(LttEventType *event_type1, + LttEventType *event_type2, + LttField *field1, LttField *field2) { - size_t size = 0; + guint different = 0; + enum field_status local_fixed_root, local_fixed_parent; guint i; - LttType *type; + LttType *type1; + LttType *type2; - 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; + if(field1 == NULL) { + if(field2 == NULL) goto end; + else { + different = 1; + goto end; + } + } else if(field2 == NULL) { + different = 1; + goto end; + } - type = field->field_type; + g_assert(field1->fixed_root != FIELD_UNKNOWN); + g_assert(field2->fixed_root != FIELD_UNKNOWN); + g_assert(field1->fixed_parent != FIELD_UNKNOWN); + g_assert(field2->fixed_parent != FIELD_UNKNOWN); + g_assert(field1->fixed_size != FIELD_UNKNOWN); + g_assert(field2->fixed_size != FIELD_UNKNOWN); - switch(type->type_class) { + type1 = field1->field_type; + type2 = field2->field_type; + + size_t current_root_offset; + size_t current_offset; + enum field_status current_child_status, final_child_status; + size_t max_size; + + if(type1->type_class != type2->type_class) { + different = 1; + goto end; + } + if(type1->element_name != type2->element_name) { + different = 1; + goto end; + } + + switch(type1->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; + if(field1->field_size != field2->field_size) { + different = 1; + goto end; + } + break; + case LTT_ENUM: + if(type1->element_number != type2->element_number) { + different = 1; + goto end; + } + for(i=0;ielement_number;i++) { + if(type1->enum_strings[i] != type2->enum_strings[i]) { + different = 1; + goto end; + } + } 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; - } + /* Two elements : size and child */ + g_assert(type1->element_number != type2->element_number); + for(i=0;ielement_number;i++) { + if(check_fields_compatibility(event_type1, event_type2, + field1->child[0], field2->child[0])) { + different = 1; + goto end; } - 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; + if(field1->field_size != field2->field_size) { + different = 1; + goto end; } - 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; - + /* Two elements : size and child */ + g_assert(type1->element_number != type2->element_number); + for(i=0;ielement_number;i++) { + if(check_fields_compatibility(event_type1, event_type2, + field1->child[0], field2->child[0])) { + different = 1; + goto end; } - size = current_offset; - field->field_size = size; } break; + case LTT_STRUCT: 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); + if(type1->element_number != type2->element_number) { + different = 1; + break; + } + for(i=0;ielement_number;i++) { + if(check_fields_compatibility(event_type1, event_type2, + field1->child[0], field2->child[0])) { + different = 1; + goto end; } - field->field_size = size; } break; } - - return size; +end: + return different; } + #if 0 /***************************************************************************** *Function name @@ -2131,7 +2186,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 @@ -2140,7 +2195,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; @@ -2159,7 +2214,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 @@ -2168,7 +2223,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; @@ -2241,6 +2296,6 @@ 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"); + LTT_TRACEFILE_NAME_FACILITIES = g_quark_from_string("/control/facilities"); }