X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Fltt%2Ftracefile.c;h=97ac57cc35f260c6c27af23e15d217f56725524e;hb=a8c0f09de06b94e9420d286e1541c39092fff434;hp=f1b14a828d28db792f52b4a86d87fb4392334318;hpb=fcdf0ec203524819d926c57c9aa4d2fb6a268ca1;p=lttv.git diff --git a/ltt/branches/poly/ltt/tracefile.c b/ltt/branches/poly/ltt/tracefile.c index f1b14a82..97ac57cc 100644 --- a/ltt/branches/poly/ltt/tracefile.c +++ b/ltt/branches/poly/ltt/tracefile.c @@ -2,96 +2,61 @@ #include #include #include +#include #include -#include #include "parser.h" -#include +#include +#include "ltt-private.h" +#include +#include -//#include "default.h" //yxx test +#define DIR_NAME_SIZE 256 /* set the offset of the fields belonging to the event, need the information of the archecture */ -void setFieldsOffset(ltt_tracefile * t, ltt_eventtype *evT, void *evD); +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) */ -int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot, - int offsetParent, ltt_field * fld, void * evD ); +int getFieldtypeSize(LttTracefile * tf, LttEventType * evT, int offsetRoot, + int 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, char * mesg); -int readBlock(ltt_tracefile * tf, int whichBlock); +int readBlock(LttTracefile * tf, int whichBlock); /* calculate cycles per nsec for current block */ -void getCyclePerNsec(ltt_tracefile * t); - -/* functions to release the memory occupied by the tables of a tracefile */ -void freeKey (gpointer key, gpointer value, gpointer user_data); -void freeValue (gpointer key, gpointer value, gpointer user_data); -void freeFacilityNameTable (gpointer key, gpointer value, gpointer user_data); +void getCyclePerNsec(LttTracefile * t); /* reinitialize the info of the block which is already in the buffer */ -void updateTracefile(ltt_tracefile * tf); +void updateTracefile(LttTracefile * tf); /* go to the next event */ -int skipEvent(ltt_tracefile * t); - -/* compare two time (ltt_time), 0:t1=t2, -1:t1t2 */ -int timecmp(ltt_time * t1, ltt_time * t2); - -/* get an integer number */ -int getIntNumber(int size1, void *evD); - - -/* Time operation macros for ltt_time (struct timespec) */ -/* (T3 = T2 - T1) */ -#define TimeSub(T3, T2, T1) \ -do \ -{\ - (T3).tv_sec = (T2).tv_sec - (T1).tv_sec; \ - (T3).tv_nsec = (T2).tv_nsec - (T1).tv_nsec; \ - if((T3).tv_nsec < 0)\ - {\ - (T3).tv_sec--;\ - (T3).tv_nsec += 1000000000;\ - }\ -} while(0) - -/* (T3 = T2 + T1) */ -#define TimeAdd(T3, T2, T1) \ -do \ -{\ - (T3).tv_sec = (T2).tv_sec + (T1).tv_sec; \ - (T3).tv_nsec = (T2).tv_nsec + (T1).tv_nsec; \ - if((T3).tv_nsec >= 1000000000)\ - {\ - (T3).tv_sec += (T3).tv_nsec / 1000000000;\ - (T3).tv_nsec = (T3).tv_nsec % 1000000000;\ - }\ -} while(0) - +int skipEvent(LttTracefile * t); /***************************************************************************** *Function name - * ltt_tracefile_open : open a trace file, construct a ltt_tracefile + * ltt_tracefile_open : open a trace file, construct a LttTracefile *Input params - * pathname : path name of the trace file + * t : the trace containing the tracefile + * fileName : path name of the trace file *Return value - * ltt_tracefile * : the structure represents the opened trace file + * : a pointer to a tracefile ****************************************************************************/ -ltt_tracefile *ltt_tracefile_open(char * fileName) +LttTracefile* ltt_tracefile_open(LttTrace * t, char * fileName) { - ltt_tracefile * tf; - struct stat lTDFStat; /* Trace data file status */ - trace_header_event *trace_header; - block_header a_block_header; + LttTracefile * tf; + struct stat lTDFStat; /* Trace data file status */ + BlockStart a_block_start; - tf = g_new(ltt_tracefile, 1); + tf = g_new(LttTracefile, 1); //open the file + tf->name = g_strdup(fileName); + tf->trace = t; tf->fd = open(fileName, O_RDONLY, 0); if(tf->fd < 0){ g_error("Unable to open input data file %s\n", fileName); @@ -103,371 +68,675 @@ ltt_tracefile *ltt_tracefile_open(char * fileName) } // Is the file large enough to contain a trace - if(lTDFStat.st_size < sizeof(block_header) + sizeof(trace_header_event)){ - g_error("The input data file %s does not contain a trace\n", fileName); + if(lTDFStat.st_size < sizeof(BlockStart) + EVENT_HEADER_SIZE){ + g_print("The input data file %s does not contain a trace\n", fileName); + g_free(tf->name); + close(tf->fd); + g_free(tf); + return NULL; } //store the size of the file tf->file_size = lTDFStat.st_size; - - //read the first block header - if(readFile(tf->fd,(void*)&a_block_header, sizeof(block_header), - "Unable to read block header")) - exit(1); - - //read the trace header event - trace_header = g_new(trace_header_event, 1); - if(readFile(tf->fd,(void*)trace_header, sizeof(trace_header_event), - "Unable to read trace header event")) - exit(1); - - tf->block_number = tf->file_size / trace_header->buffer_size; - tf->trace_header = (trace_header_event *)trace_header; + 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(char, trace_header->buffer_size); + tf->buffer = (void *) g_new(char, t->system_description->ltt_block_size); - //read the last block, get the trace end time - if(readBlock(tf,tf->block_number)) exit(1); - tf->end_time = tf->a_block_footer->time; + //read the first block + if(readBlock(tf,1)) exit(1); - //read the first block, get the trace start time - if(tf->block_number != 1) - if(readBlock(tf,1)) exit(1); - tf->start_time = tf->a_block_header->time; + return tf; +} - //get local machine's data type size and endian type - getDataEndianType(&(tf->my_arch_size), &(tf->my_arch_endian)); - //initialize all tables - tf->eventtype_number = 0; - tf->facility_number = 0; - tf->index_facility = g_hash_table_new (g_int_hash, g_int_equal); - tf->facility_name = g_hash_table_new (g_str_hash, g_str_equal); - tf->base_id_name = g_hash_table_new (g_str_hash, g_int_equal); - tf->eventtype_event_id = g_ptr_array_new(); +/***************************************************************************** + *Open control and per cpu tracefiles + ****************************************************************************/ - return tf; +void ltt_tracefile_open_cpu(LttTrace *t, char * 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); +} + +void ltt_tracefile_open_control(LttTrace *t, char * control_name) +{ + LttTracefile * tf; + LttEvent * ev; + LttFacility * f; + guint16 evId; + void * pos; + FacilityLoad fLoad; + int i; + + tf = ltt_tracefile_open(t,control_name); + if(!tf) return; + 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){ + ev = ltt_tracefile_read(tf); + if(!ev)return; // end of file + + if(ev->event_id == TRACE_FACILITY_LOAD){ + pos = ev->data; + fLoad.name = (char*)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_error("Facility: %s, checksum: %d is not founded\n", + fLoad.name,fLoad.checksum); + }else if(ev->event_id == TRACE_BLOCK_START){ + continue; + }else if(ev->event_id == TRACE_BLOCK_END){ + break; + }else g_error("Not valid facilities trace file\n"); + } + } } /***************************************************************************** *Function name - * ltt_tracefile_close: close a trace file, release all facilities if their - * usage count == 0 when close_facilities is true + * ltt_tracefile_close: close a trace file, *Input params * t : tracefile which will be closed - * close_facilities : bool to show if the facilities need to be released - *Return value - * int : ???? ****************************************************************************/ -int ltt_tracefile_close(ltt_tracefile *t, int close_facilities) +void ltt_tracefile_close(LttTracefile *t) { - //free index_facility table - g_hash_table_foreach (t->index_facility, freeKey, NULL); - g_hash_table_destroy(t->index_facility); + g_free(t->name); + g_free(t->buffer); + close(t->fd); + g_free(t); +} - //free base_id_facility table - g_hash_table_foreach (t->base_id_name, freeValue, NULL); - g_hash_table_destroy(t->base_id_name); - //free eventtype_event_id array - g_ptr_array_free (t->eventtype_event_id, TRUE); +/***************************************************************************** + *Get system information + ****************************************************************************/ +void getSystemInfo(LttSystemDescription* des, char * pathname) +{ + FILE * fp; + int i; + int entry_number = 15; + char buf[DIR_NAME_SIZE]; + char description[4*DIR_NAME_SIZE]; + char * ptr; + + fp = fopen(pathname,"r"); + if(!fp){ + g_error("Can not open file : %s\n", pathname); + } + + while(fgets(buf,DIR_NAME_SIZE, fp)!= NULL){ + ptr = buf; + while(isspace(*ptr)) ptr++; + if(strlen(ptr) == 0) continue; + break; + } + + if(strlen(ptr) == 0) g_error("Not a valid file: %s\n", pathname); + if(strncmp("node_name = g_strdup(ptr+10); + break; + case 1: + if(strncmp("domainname=",ptr,11)!=0) + g_error("Not a valid file: %s\n", pathname); + des->domain_name = g_strdup(ptr+11); + break; + case 2: + if(strncmp("cpu=",ptr,4)!=0) + g_error("Not a valid file: %s\n", pathname); + des->nb_cpu = (unsigned)atoi(ptr+4); + break; + case 3: + if(strncmp("arch_size=",ptr,10)!=0) + g_error("Not a valid file: %s\n", pathname); + if(strcmp(ptr+10,"\"LP32\"") == 0) des->size = LTT_LP32; + else if(strcmp(ptr+10,"\"ILP32\"") == 0) des->size = LTT_ILP32; + else if(strcmp(ptr+10,"\"LP64\"") == 0) des->size = LTT_LP64; + else if(strcmp(ptr+10,"\"ILP64\"") == 0) des->size = LTT_ILP64; + else if(strcmp(ptr+10,"\"UNKNOWN\"") == 0) des->size = LTT_UNKNOWN; + break; + case 4: + if(strncmp("endian=",ptr,7)!=0) + g_error("Not a valid file: %s\n", pathname); + if(strcmp(ptr+7,"\"LITTLE_ENDIAN\"") == 0) + des->endian = LTT_LITTLE_ENDIAN; + else if(strcmp(ptr+7,"\"BIG_ENDIAN\"") == 0) + des->endian = LTT_BIG_ENDIAN; + break; + case 5: + if(strncmp("kernel_name=",ptr,12)!=0) + g_error("Not a valid file: %s\n", pathname); + des->kernel_name = g_strdup(ptr+12); + break; + case 6: + if(strncmp("kernel_release=",ptr,15)!=0) + g_error("Not a valid file: %s\n", pathname); + des->kernel_release = g_strdup(ptr+15); + break; + case 7: + if(strncmp("kernel_version=",ptr,15)!=0) + g_error("Not a valid file: %s\n", pathname); + des->kernel_version = g_strdup(ptr+15); + break; + case 8: + if(strncmp("machine=",ptr,8)!=0) + g_error("Not a valid file: %s\n", pathname); + des->machine = g_strdup(ptr+8); + break; + case 9: + if(strncmp("processor=",ptr,10)!=0) + g_error("Not a valid file: %s\n", pathname); + des->processor = g_strdup(ptr+10); + break; + case 10: + if(strncmp("hardware_platform=",ptr,18)!=0) + g_error("Not a valid file: %s\n", pathname); + des->hardware_platform = g_strdup(ptr+18); + break; + case 11: + if(strncmp("operating_system=",ptr,17)!=0) + g_error("Not a valid file: %s\n", pathname); + des->operating_system = g_strdup(ptr+17); + break; + case 12: + if(strncmp("ltt_major_version=",ptr,18)!=0) + g_error("Not a valid file: %s\n", pathname); + ptr += 18; + // ptr++;//skip begining " + // ptr[strlen(ptr)-1] = '\0'; //get rid of the ending " + des->ltt_major_version = (unsigned)atoi(ptr); + break; + case 13: + if(strncmp("ltt_minor_version=",ptr,18)!=0) + g_error("Not a valid file: %s\n", pathname); + ptr += 18; + // ptr++;//skip begining " + // ptr[strlen(ptr)-1] = '\0'; //get rid of the ending " + des->ltt_minor_version = (unsigned)atoi(ptr); + break; + case 14: + if(strncmp("ltt_block_size=",ptr,15)!=0) + g_error("Not a valid file: %s\n", pathname); + ptr += 15; + // ptr++;//skip begining " + // ptr[strlen(ptr)-1] = '\0'; //get rid of the ending " + des->ltt_block_size = (unsigned)atoi(ptr); + break; + default: + g_error("Not a valid file: %s\n", pathname); + } + } - //free facility_name table - g_hash_table_foreach (t->facility_name, freeFacilityNameTable, - GINT_TO_POINTER(1)); - g_hash_table_destroy(t->facility_name); + //get description + description[0] = '\0'; + if(fgets(buf,DIR_NAME_SIZE, fp)== NULL) + g_error("Not a valid file: %s\n", pathname); + ptr = buf; + while(isspace(*ptr)) ptr++; + if(*ptr != '>') g_error("Not a valid file: %s\n", pathname); + while((ptr=fgets(buf,DIR_NAME_SIZE, fp))!= NULL){ + ptr = buf; + while(isspace(*ptr)) ptr++; + if(strncmp("",ptr,9) == 0 )break; + strcat(description, buf); + } + if(!ptr)g_error("Not a valid file: %s\n", pathname); + if(description[0] = '\0')des->description = NULL; + des->description = g_strdup(description); - //free tracefile structure - g_free(t->trace_header); - g_free(t->buffer); - g_free(t); - return 0; + fclose(fp); } /***************************************************************************** - * functions to release the memory occupied by the tables of a tracefile + *The following functions get facility/tracefile information ****************************************************************************/ -void freeKey (gpointer key, gpointer value, gpointer user_data) +void getFacilityInfo(LttTrace *t, char* eventdefs) { - g_free(key); + DIR * dir; + struct dirent *entry; + char * ptr; + int i,j; + LttFacility * f; + LttEventType * et; + char name[DIR_NAME_SIZE]; + + dir = opendir(eventdefs); + if(!dir) g_error("Can not open directory: %s\n", eventdefs); + + while((entry = readdir(dir)) != NULL){ + ptr = &entry->d_name[strlen(entry->d_name)-4]; + if(strcmp(ptr,".xml") != 0) continue; + strcpy(name,eventdefs); + strcat(name,entry->d_name); + ltt_facility_open(t,name); + } + closedir(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); + } + } } -void freeValue (gpointer key, gpointer value, gpointer user_data) +void getControlFileInfo(LttTrace *t, char* control) { - g_free(value); + DIR * dir; + struct dirent *entry; + char name[DIR_NAME_SIZE]; + + dir = opendir(control); + if(!dir) g_error("Can not open directory: %s\n", control); + + while((entry = readdir(dir)) != NULL){ + if(strcmp(entry->d_name,"facilities") != 0 && + strcmp(entry->d_name,"interrupts") != 0 && + strcmp(entry->d_name,"processes") != 0) continue; + + strcpy(name,control); + strcat(name,entry->d_name); + ltt_tracefile_open_control(t,name); + } + closedir(dir); } -void freeFacilityNameTable (gpointer key, gpointer value, gpointer user_data) +void getCpuFileInfo(LttTrace *t, char* cpu) { - ltt_facility * fac = (ltt_facility*) value; - fac->usage_count--; - if(GPOINTER_TO_INT(user_data) != 0) - ltt_facility_close(fac); + DIR * dir; + struct dirent *entry; + char name[DIR_NAME_SIZE]; + + dir = opendir(cpu); + if(!dir) g_error("Can not open directory: %s\n", cpu); + + while((entry = readdir(dir)) != NULL){ + if(strcmp(entry->d_name,".") != 0 && + strcmp(entry->d_name,"..") != 0 ){ + strcpy(name,cpu); + strcat(name,entry->d_name); + ltt_tracefile_open_cpu(t,name); + }else continue; + } + closedir(dir); } /***************************************************************************** - *Function name - * ltt_tracefile_facility_add: increases the facility usage count and also - * specifies the base of the numeric range - * assigned to the event types in the facility - * for this tracefile - *Input params - * t : tracefile that the facility will be added - * f : facility that will be attached to the tracefile - * base_id : the id for the first event of the facility in the - * trace file - *Return value - * int : ???? + *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. ****************************************************************************/ -int ltt_tracefile_facility_add(ltt_tracefile *t,ltt_facility *f,int base_id) +LttTrace *ltt_trace_open(const char *pathname) { - int * id, *index; - int i, j, k; - ltt_eventtype * et; - gpointer tmpPtr; + LttTrace * t; + LttSystemDescription * sys_description; + char eventdefs[DIR_NAME_SIZE]; + char info[DIR_NAME_SIZE]; + char control[DIR_NAME_SIZE]; + char cpu[DIR_NAME_SIZE]; + char tmp[DIR_NAME_SIZE]; + gboolean has_slash = FALSE; + + //establish the pathname to different directories + if(pathname[strlen(pathname)-1] == '/')has_slash = TRUE; + strcpy(eventdefs,pathname); + if(!has_slash)strcat(eventdefs,"/"); + strcat(eventdefs,"eventdefs/"); + + strcpy(info,pathname); + if(!has_slash)strcat(info,"/"); + strcat(info,"info/"); + + strcpy(control,pathname); + if(!has_slash)strcat(control,"/"); + strcat(control,"control/"); + + strcpy(cpu,pathname); + if(!has_slash)strcat(cpu,"/"); + strcat(cpu,"cpu/"); + + //new trace + t = g_new(LttTrace, 1); + sys_description = g_new(LttSystemDescription, 1); + t->pathname = g_strdup(pathname); + 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"); + getSystemInfo(sys_description, tmp); + + //get facilities info + getFacilityInfo(t,eventdefs); + + //get control tracefile info + getControlFileInfo(t,control); - //increase the facility usage count - f->usage_count++; - t->eventtype_number += f->event_number; - t->facility_number++; + //get cpu tracefile info + getCpuFileInfo(t,cpu); - //insert the facility into index_facility table - id = g_new(int,1); - *id = t->facility_number; - g_hash_table_insert(t->index_facility, (gpointer)id,(gpointer)f); + return t; +} - //insert facility name into table: base_id_name - id = g_new(int,1); - *id = base_id; - g_hash_table_insert(t->base_id_name, (gpointer)(f->name), (gpointer)id); +char * ltt_trace_name(LttTrace *t) +{ + return t->pathname; +} - //insert facility name into table: facility_name - g_hash_table_insert(t->facility_name, (gpointer)(f->name), (gpointer)f); - - //insert eventtype into the array: eventtype_event_id - j = base_id + f->event_number; - k = t->eventtype_event_id->len; - if(j > t->eventtype_event_id->len){ - for(i=0; i < j - k; i++){ - tmpPtr = (gpointer)g_new(ptr_wrap, 1); - g_ptr_array_add(t->eventtype_event_id,tmpPtr); - } - } - //initialize the unused elements: NULL - if(j-k > f->event_number){ - for(i=k; ieventtype_event_id, i); - ((ptr_wrap*)tmpPtr)->ptr = NULL; - } - } +/****************************************************************************** + * 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) +{ + int i; + LttTracefile * tf; + LttFacility * f; - //initialize the elements with the eventtypes belonging to the facility - for(i=0; ievent_number; i++){ - tmpPtr = g_ptr_array_index(t->eventtype_event_id, base_id + i); - ((ptr_wrap*)tmpPtr)->ptr = (gpointer)(f->events[i]); + 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); } - - //update offset - for(i=0; ievent_number; i++){ - et = f->events[i]; - setFieldsOffset(t, et, NULL); + 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); - return 0; + g_free(t); + + g_blow_chunks(); } + /***************************************************************************** - * The following functions used to query the info of the machine where the - * tracefile was generated. A tracefile may be queried for its architecture - * type(e.g.,"i386", "powerpc", "powerpcle", "s390", "s390x"), its architecture - * variant(e.g., "att" versus "sun" for m68k), its operating system (e.g., - * "linux","bsd"), its generic architecture, and the machine identity (e.g., - * system host name). All character strings belong to the associated tracefile - * and are freed when it is closed + *Get the system description of the trace ****************************************************************************/ -uint32_t ltt_tracefile_arch_type(ltt_tracefile *t) -{ - return t->trace_header->arch_type; -} - -uint32_t ltt_tracefile_arch_variant(ltt_tracefile *t) -{ - return t->trace_header->arch_variant; -} - -ltt_arch_size ltt_tracefile_arch_size(ltt_tracefile *t) +LttSystemDescription *ltt_trace_system_description(LttTrace *t) { - return t->trace_header->arch_size; + return t->system_description; } -ltt_arch_endian ltt_tracefile_arch_endian(ltt_tracefile *t) -{ - return t->trace_header->arch_endian; -} +/***************************************************************************** + * The following functions discover the facilities of the trace + ****************************************************************************/ -uint32_t ltt_tracefile_system_type(ltt_tracefile *t) +unsigned ltt_trace_facility_number(LttTrace *t) { - return t->trace_header->system_type; + return (unsigned)(t->facility_number); } -char *ltt_tracefile_system_name(ltt_tracefile *t) +LttFacility *ltt_trace_facility_get(LttTrace *t, unsigned i) { - return t->trace_header->system_name; + return (LttFacility*)g_ptr_array_index(t->facilities, i); } /***************************************************************************** *Function name - * ltt_tracefile_cpu_number: get the number of the cpu + * ltt_trace_facility_find : find facilities in the trace *Input params - * t : tracefile + * t : the trace + * name : facility name + *Output params + * position : position of the facility in the trace *Return value - * unsigned : the number of cpu the system has + * : the number of facilities ****************************************************************************/ -unsigned ltt_tracefile_cpu_number(ltt_tracefile *t) +unsigned ltt_trace_facility_find(LttTrace *t, char *name, unsigned *position) { - return (unsigned)(t->trace_header->cpu_number); + 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; } /***************************************************************************** - *Function name - * ltt_tracefile_cpu_single: does the tracefile contain events only for a - * single CPU ? - *Input params - * t : tracefile - *Return value - * int : 1 for YES, 0 for NO + * Functions to discover all the event types in the trace ****************************************************************************/ -int ltt_tracefile_cpu_single(ltt_tracefile *t) +unsigned ltt_trace_eventtype_number(LttTrace *t) { - if(t->trace_header->cpu_number_used == 1) return 1; - else return 0; + int i; + unsigned count = 0; + LttFacility * f; + for(i=0;ifacility_number;i++){ + f = (LttFacility*)g_ptr_array_index(t->facilities, i); + count += f->event_number; + } + return count; } -/***************************************************************************** - *Function name - * ltt_tracefile_cpu_id: which CPU is contained in the tracefile? - *Input params - * t : tracefile - *Return value - * unsigned : cpu id - ****************************************************************************/ +LttFacility * ltt_trace_facility_by_id(LttTrace * trace, unsigned id) +{ + LttFacility * facility; + int i; + for(i=0;ifacility_number;i++){ + facility = (LttFacility*) g_ptr_array_index(trace->facilities,i); + if(id >= facility->base_id && + id < facility->base_id + facility->event_number) + break; + } + if(i==trace->facility_number) return NULL; + else return facility; +} -unsigned ltt_tracefile_cpu_id(ltt_tracefile *t) +LttEventType *ltt_trace_eventtype_get(LttTrace *t, unsigned evId) { - return (unsigned)(t->trace_header->cpu_id); + LttFacility * f; + f = ltt_trace_facility_by_id(t,evId); + if(!f) return NULL; + return f->events[evId - f->base_id]; } /***************************************************************************** - * The following functions get the times related to the tracefile + *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; +} -ltt_time ltt_tracefile_time_start(ltt_tracefile *t) +unsigned ltt_trace_per_cpu_tracefile_number(LttTrace *t) { - return t->start_time; + return t->per_cpu_tracefile_number; } -ltt_time ltt_tracefile_time_end(ltt_tracefile *t) +/***************************************************************************** + *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, char *name) { - return t->end_time; + LttTracefile * tracefile; + 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; } -ltt_time ltt_tracefile_duration(ltt_tracefile *t) +int ltt_trace_per_cpu_tracefile_find(LttTrace *t, unsigned i) { - ltt_time T; - TimeSub(T, t->end_time, t->start_time); - return T; + LttTracefile * tracefile; + int j, name; + for(j=0;jper_cpu_tracefile_number;j++){ + tracefile = (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles, j); + name = atoi(tracefile->name); + if(name == (int)i)break; + } + if(j == t->per_cpu_tracefile_number) return -1; + return j; } /***************************************************************************** - * The following functions discover the facilities added to the tracefile + *Get a specific tracefile ****************************************************************************/ -unsigned ltt_tracefile_facility_number(ltt_tracefile *t) +LttTracefile *ltt_trace_control_tracefile_get(LttTrace *t, unsigned i) { - return (unsigned)(t->facility_number); -} - -ltt_facility *ltt_tracefile_facility_get(ltt_tracefile *t, unsigned i) -{ - gconstpointer ptr = (gconstpointer)(&i); - if(i<=0 || i> t->facility_number)return NULL; - return (ltt_facility*)g_hash_table_lookup(t->index_facility,ptr); + return (LttTracefile*)g_ptr_array_index(t->control_tracefiles, i); } -ltt_facility *ltt_tracefile_facility_get_by_name(ltt_tracefile *t,char *name) +LttTracefile *ltt_trace_per_cpu_tracefile_get(LttTrace *t, unsigned i) { - ltt_facility * fac; - fac=(ltt_facility*)g_hash_table_lookup(t->facility_name,(gconstpointer)name); - return fac; + return (LttTracefile*)g_ptr_array_index(t->per_cpu_tracefiles, i); } /***************************************************************************** - * The following functions to discover all the event types in the facilities - * added to the tracefile. The event type integer id, unique for the trace, - * is used + * Get the start time and end time of the trace ****************************************************************************/ -unsigned ltt_tracefile_eventtype_number(ltt_tracefile *t) +void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end) { - return t->eventtype_number; -} + LttTime startSmall, startTmp, endBig, endTmp; + 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 = tf->a_block_start->time; + readBlock(tf,tf->block_number); + endTmp = 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; + } -ltt_eventtype *ltt_tracefile_eventtype_get(ltt_tracefile *t, unsigned evId) -{ - ptr_wrap * ptr; - ptr = (ptr_wrap *)g_ptr_array_index(t->eventtype_event_id, (gint)evId); - return (ltt_eventtype *)(ptr->ptr); + for(i=0;iper_cpu_tracefile_number;i++){ + tf = g_ptr_array_index(t->per_cpu_tracefiles, i); + readBlock(tf,1); + startTmp = tf->a_block_start->time; + readBlock(tf,tf->block_number); + endTmp = 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; + } + + *start = startSmall; + *end = endBig; } + /***************************************************************************** - *Function name - * ltt_tracefile_eventtype_id - * : given an event type, find its unique id within - * the tracefile - *Input params - * t : tracefile - * et : event type - *Return value - * unsigned : id of the event type in the tracefile + *Get the name of a tracefile ****************************************************************************/ -unsigned ltt_tracefile_eventtype_id(ltt_tracefile *t, ltt_eventtype *et) +char *ltt_tracefile_name(LttTracefile *tf) { - int *id; - char *name = et->facility->name; - - id = (int*)g_hash_table_lookup(t->base_id_name, (gconstpointer)name); - if(!id)return 0; - return (unsigned)(*id + et->index); + return tf->name; } /***************************************************************************** - *Function name - * ltt_tracefile_eventtype_root_field - * : get the root field associated with an event type - * for the tracefile - *Input params - * t : tracefile - * id : event id - *Return value - * ltt_field * : root field of the event + * Get the number of blocks in the tracefile ****************************************************************************/ -ltt_field *ltt_tracefile_eventtype_root_field(ltt_tracefile *t, unsigned id) +unsigned ltt_tracefile_block_number(LttTracefile *tf) { - ltt_eventtype * et; - et = ltt_tracefile_eventtype_get(t, id); - if(!et) return NULL; - return et->root_field; + return tf->block_number; } /***************************************************************************** @@ -477,91 +746,213 @@ ltt_field *ltt_tracefile_eventtype_root_field(ltt_tracefile *t, unsigned id) *Input params * t : tracefile * time : criteria of the time - *Return value - * int : error code - * ENOENT, end of the file - * EINVAL, lseek fail - * EIO, can not read from the file ****************************************************************************/ +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(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(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); -int ltt_tracefile_seek_time(ltt_tracefile *t, ltt_time time) + headTime = ltt_time_compare(t->a_block_start->time, time); + tailTime = ltt_time_compare(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(t->a_block_start->time, time); + t_time = ltt_time_compare(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(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; - ltt_time lttTime; - int headTime = timecmp(&(t->a_block_header->time), &time); - int tailTime = timecmp(&(t->a_block_footer->time), &time); - + LttTime lttTime; + int headTime = ltt_time_compare(t->a_block_start->time, time); + int tailTime = ltt_time_compare(t->a_block_end->time, time); + LttEvent * ev; + if(headTime < 0 && tailTime > 0){ - lttTime = getEventTime(t); - err = timecmp(<tTime, &time); - if(err >= 0){ - if( ( (t->which_block != 1 && t->which_event != 0) || - (t->which_block == 1 && t->which_event != 1) ) && - ((t->prev_event_time.tv_sec==0 && t->prev_event_time.tv_nsec==0) || - timecmp(&t->prev_event_time, &time) >= 0 ) ){ - updateTracefile(t); - return ltt_tracefile_seek_time(t, time); - } - }else if(err < 0){ - err = t->which_block; - if(ltt_tracefile_read(t) == NULL) return ENOENT; - if(t->which_block == err) - return ltt_tracefile_seek_time(t,time); - } - }else if(headTime > 0){ + if(ltt_time_compare(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 || (&t->prev_event_time,&time)<0){ + return; + }else{ + updateTracefile(t); + return ltt_tracefile_seek_time(t, time); + } + }else if(err < 0){ + while(1){ + ev = ltt_tracefile_read(t); + if(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( (t->prev_block_end_time.tv_sec == 0 && - t->prev_block_end_time.tv_nsec == 0 ) || - timecmp(&(t->prev_block_end_time),&time) > 0 ){ - err=readBlock(t,t->which_block-1); - if(err) return err; - return ltt_tracefile_seek_time(t, time) ; + 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){ + }else if(tailTime < 0){ if(t->which_block != t->block_number){ - err=readBlock(t,t->which_block+1); - if(err) return err; - }else return ENOENT; - if(tailTime < 0) return ltt_tracefile_seek_time(t, time); - }else if(headTime == 0){ - updateTracefile(t); + 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; } - return 0; +} + +/***************************************************************************** + * Seek to the first event with position equal or larger to ep + ****************************************************************************/ + +void ltt_tracefile_seek_position(LttTracefile *t, LttEventPosition *ep) +{ + //if we are at the right place, just return + if(t->which_block == ep->block_num && t->which_event == ep->event_num) + return; + + if(t->which_block == ep->block_num) updateTracefile(t); + else readBlock(t,ep->block_num); + + //event offset is availiable + if(ep->old_position){ + t->cur_heart_beat_number = ep->heart_beat_number; + t->cur_event_pos = t->buffer + ep->event_offset; + return; + } + + //only block number and event index are availiable + while(t->which_event < ep->event_num) ltt_tracefile_read(t); + + return; } /***************************************************************************** *Function name - * ltt_tracefile_read : read the next event + * ltt_tracefile_read : read the current event, set the pointer to the next *Input params * t : tracefile *Return value - * ltt_event * : an event to be processed + * LttEvent * : an event to be processed ****************************************************************************/ -ltt_event *ltt_tracefile_read(ltt_tracefile *t) +LttEvent *ltt_tracefile_read(LttTracefile *t) { - ltt_event * lttEvent = (ltt_event *)g_new(ltt_event, 1); - ltt_eventtype * evT; - ltt_facility * fac; + LttEvent * lttEvent = &t->an_event; + int err; - //update the fields of the current event and go to the next event - if(skipEvent(t)) return NULL; + if(t->cur_event_pos == t->buffer + t->block_size){ + if(t->which_block == t->block_number){ + return NULL; + } + err = readBlock(t, t->which_block + 1); + if(err)g_error("Can not read tracefile"); + } - t->current_event_time = getEventTime(t); + lttEvent->event_id = (int)(*(guint16 *)(t->cur_event_pos)); + if(lttEvent->event_id == TRACE_TIME_HEARTBEAT) + t->cur_heart_beat_number++; + + t->prev_event_time = t->current_event_time; + // t->current_event_time = getEventTime(t); + + lttEvent->time_delta = *(guint32 *)(t->cur_event_pos + EVENT_ID_SIZE); + lttEvent->event_time = t->current_event_time; - lttEvent->event_id = (int)(*(uint8_t *)(t->cur_event_pos)); - evT = ltt_tracefile_eventtype_get(t, (unsigned)lttEvent->event_id); - fac = evT->facility; - // if(evT->index == TRACE_EV_HEARTBEAT && strcmp(fac->name, "default")==0) - // t->cur_heart_beat_number++; - lttEvent->cycle_count=*(uint32_t*)(t->cur_event_pos + EVENT_ID_SIZE); lttEvent->tracefile = t; lttEvent->data = t->cur_event_pos + EVENT_HEADER_SIZE; + lttEvent->which_block = t->which_block; + lttEvent->which_event = t->which_event; + + //update the fields of the current event and go to the next event + err = skipEvent(t); + if(err == ERANGE) g_error("event id is out of range\n"); + + lttEvent->event_cycle_count = t->cur_cycle_count; return lttEvent; } @@ -602,47 +993,42 @@ int readFile(int fd, void * buf, size_t size, char * mesg) * EIO : can not read from the file ****************************************************************************/ -int readBlock(ltt_tracefile * tf, int whichBlock) +int readBlock(LttTracefile * tf, int whichBlock) { off_t nbBytes; - uint32_t lostSize; + guint32 lostSize; if(whichBlock - tf->which_block == 1 && tf->which_block != 0){ - tf->prev_block_end_time = tf->a_block_footer->time; + tf->prev_block_end_time = tf->a_block_end->time; + tf->prev_event_time = 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; } - tf->prev_event_time.tv_sec = 0; - tf->prev_event_time.tv_nsec = 0; - nbBytes=lseek(tf->fd,(off_t)((whichBlock-1)*tf->trace_header->buffer_size), - SEEK_SET); + nbBytes=lseek(tf->fd,(off_t)((whichBlock-1)*tf->block_size), SEEK_SET); if(nbBytes == -1) return EINVAL; - if(readFile(tf->fd,tf->buffer,tf->trace_header->buffer_size, - "Unable to read a block")) return EIO; + if(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 - + lostSize + EVENT_HEADER_SIZE); + tf->last_event_pos = tf->buffer + tf->block_size - lostSize; - tf->a_block_header=(block_header *) tf->buffer; - lostSize = *(uint32_t*)(tf->buffer + tf->trace_header->buffer_size - - sizeof(uint32_t)); - /* skip event ID and time delta to get the address of the block foot */ - tf->a_block_footer=(block_footer *)(tf->buffer+tf->trace_header->buffer_size - -lostSize+sizeof(uint8_t)+sizeof(uint32_t)); tf->which_block = whichBlock; - tf->which_event = 0; - tf->first_event_pos = tf->buffer + sizeof(block_header); - if(tf->which_block == 1){ - tf->which_event++; - tf->first_event_pos += sizeof(trace_header_event); - } - tf->cur_event_pos = tf->first_event_pos; - tf->current_event_time = tf->a_block_header->time; + tf->which_event = 1; + tf->cur_event_pos = tf->buffer;//the beginning of the block, block start ev tf->cur_heart_beat_number = 0; - + getCyclePerNsec(tf); + tf->current_event_time = getEventTime(tf); + return 0; } @@ -654,12 +1040,11 @@ int readBlock(ltt_tracefile * tf, int whichBlock) * tf : tracefile ****************************************************************************/ -void updateTracefile(ltt_tracefile * tf) +void updateTracefile(LttTracefile * tf) { - if(tf->which_block == 1)tf->which_event = 1; - else tf->which_event = 0; - tf->cur_event_pos = tf->first_event_pos; - tf->current_event_time = tf->a_block_header->time; + 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; @@ -673,45 +1058,42 @@ void updateTracefile(ltt_tracefile * tf) * t : tracefile *return value * 0 : success - * EINVAL : lseek fail - * EIO : can not read from the file - * ENOENT : end of file * ERANGE : event id is out of range ****************************************************************************/ -int skipEvent(ltt_tracefile * t) +int skipEvent(LttTracefile * t) { int evId, err; void * evData; - ltt_eventtype * evT; - ltt_field * rootFld; + LttEventType * evT; + LttField * rootFld; - evId = (int)(*(uint8_t *)(t->cur_event_pos)); + evId = (int)(*(guint16 *)(t->cur_event_pos)); evData = t->cur_event_pos + EVENT_HEADER_SIZE; - evT = ltt_tracefile_eventtype_get(t,(unsigned)evId); + evT = ltt_trace_eventtype_get(t->trace,(unsigned)evId); + if(evT) rootFld = evT->root_field; else return ERANGE; - - t->prev_event_time = getEventTime(t); - //event has string/sequence or the last event is not the same event - if((evT->latest_block!=t->which_block || evT->latest_event!=t->which_event) - && rootFld->field_fixed == 0){ - setFieldsOffset(t, evT, evData); - } - t->cur_event_pos += EVENT_HEADER_SIZE + rootFld->field_size; - + if(rootFld){ + //event has string/sequence or the last event is not the same event + if((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(t->which_event == t->a_block_header->event_count - 1){ - if(t->which_block == t->block_number) return ENOENT; - err = readBlock(t, t->which_block + 1); - if(err) return err; + if(evId == TRACE_BLOCK_END){ + t->cur_event_pos = t->buffer + t->block_size; }else{ t->which_event++; + t->current_event_time = getEventTime(t); } return 0; @@ -724,21 +1106,23 @@ int skipEvent(ltt_tracefile * t) * t : tracefile ****************************************************************************/ -void getCyclePerNsec(ltt_tracefile * t) +void getCyclePerNsec(LttTracefile * t) { - ltt_time lBufTotalTime; /* Total time for this buffer */ - ltt_cycle_count lBufTotalNSec; /* Total time for this buffer in nsecs */ - ltt_cycle_count lBufTotalCycle;/* Total cycles for this buffer */ + LttTime lBufTotalTime; /* Total time for this buffer */ + LttCycleCount lBufTotalNSec; /* Total time for this buffer in nsecs */ + LttCycleCount lBufTotalCycle;/* Total cycles for this buffer */ /* Calculate the total time for this buffer */ - TimeSub(lBufTotalTime,t->a_block_footer->time, t->a_block_header->time); + lBufTotalTime = ltt_time_sub(t->a_block_end->time, t->a_block_start->time); /* Calculate the total cycles for this bufffer */ - lBufTotalCycle = t->a_block_footer->cycle_count - - t->a_block_header->cycle_count; + lBufTotalCycle = t->a_block_end->cycle_count; + lBufTotalCycle -= t->a_block_start->cycle_count; /* Convert the total time to nsecs */ - lBufTotalNSec = lBufTotalTime.tv_sec * 1000000000 + lBufTotalTime.tv_nsec; + lBufTotalNSec = lBufTotalTime.tv_sec; + lBufTotalNSec *= NANOSECONDS_PER_SECOND; + lBufTotalNSec += lBufTotalTime.tv_nsec; t->cycle_per_nsec = (double)lBufTotalCycle / (double)lBufTotalNSec; } @@ -749,32 +1133,59 @@ void getCyclePerNsec(ltt_tracefile * t) *Input params * tf : tracefile *Return value - * ltt_time : the time of the event + * LttTime : the time of the event ****************************************************************************/ -ltt_time getEventTime(ltt_tracefile * tf) +LttTime getEventTime(LttTracefile * tf) { - ltt_time time; - ltt_cycle_count cycle_count; /* cycle count for the current event */ - ltt_cycle_count lEventTotalCycle; /* Total cycles from start for event */ - double lEventNSec; /* Total usecs from start for event */ - ltt_time lTimeOffset; /* Time offset in struct ltt_time */ + LttTime time; + LttCycleCount cycle_count; // cycle count for the current event + LttCycleCount lEventTotalCycle; // Total cycles from start for event + double lEventNSec; // Total usecs from start for event + LttTime lTimeOffset; // Time offset in struct LttTime + guint16 evId; + gint64 nanoSec, tmpCycleCount = (((guint64)1)<<32); + static LttCycleCount preCycleCount = 0; + static int count = 0; + + evId = *(guint16 *)tf->cur_event_pos; + if(evId == TRACE_BLOCK_START){ + count = 0; + preCycleCount = 0; + tf->cur_cycle_count = tf->a_block_start->cycle_count; + return tf->a_block_start->time; + }else if(evId == TRACE_BLOCK_END){ + count = 0; + preCycleCount = 0; + tf->cur_cycle_count = tf->a_block_end->cycle_count; + return tf->a_block_end->time; + } + + // Calculate total time in cycles from start of buffer for this event + cycle_count = (LttCycleCount)*(guint32 *)(tf->cur_event_pos + EVENT_ID_SIZE); + + if(cycle_count < preCycleCount)count++; + preCycleCount = cycle_count; + cycle_count += tmpCycleCount * count; - /* Calculate total time in cycles from start of buffer for this event */ - cycle_count = *(uint32_t*)(tf->cur_event_pos + EVENT_ID_SIZE); - if(tf->cur_heart_beat_number) - cycle_count += ((uint64_t)1)<<32 * tf->cur_heart_beat_number; - lEventTotalCycle=cycle_count-(tf->a_block_header->cycle_count & 0xFFFFFFFF); + if(tf->cur_heart_beat_number > count) + cycle_count += tmpCycleCount * (tf->cur_heart_beat_number - count); - /* Convert it to nsecs */ + tf->cur_cycle_count = cycle_count; + + lEventTotalCycle = cycle_count; + lEventTotalCycle -= tf->a_block_start->cycle_count; + + // Convert it to nsecs lEventNSec = lEventTotalCycle / tf->cycle_per_nsec; - - /* Determine offset in struct ltt_time */ - lTimeOffset.tv_nsec = (long)lEventNSec % 1000000000; - lTimeOffset.tv_sec = (long)lEventNSec / 1000000000; + nanoSec = lEventNSec; - TimeAdd(time, tf->a_block_header->time, lTimeOffset); + // Determine offset in struct LttTime + lTimeOffset.tv_nsec = nanoSec % NANOSECONDS_PER_SECOND; + lTimeOffset.tv_sec = nanoSec / NANOSECONDS_PER_SECOND; + time = ltt_time_add(tf->a_block_start->time, lTimeOffset); + return time; } @@ -787,12 +1198,13 @@ ltt_time getEventTime(ltt_tracefile * tf) * evD : event data, it may be NULL ****************************************************************************/ -void setFieldsOffset(ltt_tracefile * t, ltt_eventtype * evT, void * evD) +void setFieldsOffset(LttTracefile *tf,LttEventType *evT,void *evD,LttTrace* t) { - ltt_field * rootFld = evT->root_field; + LttField * rootFld = evT->root_field; // rootFld->base_address = evD; - rootFld->field_size = getFieldtypeSize(t, evT, 0,0,rootFld, evD); + if(rootFld) + rootFld->field_size = getFieldtypeSize(tf, evT, 0,0,rootFld, evD,t); } /***************************************************************************** @@ -809,15 +1221,17 @@ void setFieldsOffset(ltt_tracefile * t, ltt_eventtype * evT, void * evD) * int : size of the field ****************************************************************************/ -int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot, - int offsetParent, ltt_field * fld, void * evD) +int getFieldtypeSize(LttTracefile * t, LttEventType * evT, int offsetRoot, + int offsetParent, LttField * fld, void *evD, LttTrace *trace) { int size, size1, element_number, i, offset1, offset2; - ltt_type * type = fld->field_type; + LttType * type = fld->field_type; - if(evT->latest_block==t->which_block && evT->latest_event==t->which_event){ - return fld->field_size; - } + if(t){ + if(evT->latest_block==t->which_block && evT->latest_event==t->which_event){ + return fld->field_size; + } + } if(fld->field_fixed == 1){ if(fld == evT->root_field) return fld->field_size; @@ -826,14 +1240,14 @@ int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot, if(type->type_class != LTT_STRUCT && type->type_class != LTT_ARRAY && type->type_class != LTT_SEQUENCE && type->type_class != LTT_STRING){ if(fld->field_fixed == -1){ - size = (int) ltt_type_size(t, type); + size = (int) ltt_type_size(trace, type); fld->field_fixed = 1; }else size = fld->field_size; }else if(type->type_class == LTT_ARRAY){ element_number = (int) type->element_number; if(fld->field_fixed == -1){ - size = getFieldtypeSize(t, evT, offsetRoot,0,fld->child[0], NULL); + size = getFieldtypeSize(t, evT, offsetRoot,0,fld->child[0], NULL, trace); if(size == 0){ //has string or sequence fld->field_fixed = 0; }else{ @@ -844,15 +1258,16 @@ int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot, size = 0; for(i=0;ichild[0], evD+size); + fld->child[0], evD+size, trace); } }else size = fld->field_size; }else if(type->type_class == LTT_SEQUENCE){ - size1 = (int) ltt_type_size(t, type); + 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); + size = getFieldtypeSize(t, evT, offsetRoot,0,fld->child[0], NULL, trace); fld->element_size = size; }else{//0: sequence element_number = getIntNumber(size1,evD); @@ -863,7 +1278,7 @@ int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot, size = 0; for(i=0;ichild[0], evD+size+size1); + fld->child[0], evD+size+size1, trace); } } size += size1; @@ -874,7 +1289,7 @@ int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot, if(fld->field_fixed == -1){ fld->field_fixed = 0; }else{//0: string - size = sizeof((char*)evD) + 1; //include end : '\0' + size = strlen((char*)evD) + 1; //include end : '\0' } }else if(type->type_class == LTT_STRUCT){ @@ -884,7 +1299,7 @@ int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot, offset1 = offsetRoot; offset2 = 0; for(i=0;ichild[i], NULL); + size1=getFieldtypeSize(t, evT,offset1,offset2, fld->child[i], NULL, trace); if(size1 > 0 && size >= 0){ size += size1; if(offset1 >= 0) offset1 += size1; @@ -903,7 +1318,7 @@ int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot, offset1 = offsetRoot; offset2 = 0; for(i=0;ichild[i],evD+offset2); + size=getFieldtypeSize(t,evT,offset1,offset2,fld->child[i],evD+offset2, trace); offset1 += size; offset2 += size; } @@ -922,24 +1337,6 @@ int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot, return size; } -/***************************************************************************** - *Function name - * timecmp : compare two time - *Input params - * t1 : first time - * t2 : second time - *Return value - * int : 0: t1 == t2; -1: t1 < t2; 1: t1 > t2 - ****************************************************************************/ - -int timecmp(ltt_time * t1, ltt_time * t2) -{ - ltt_time T; - TimeSub(T, *t1, *t2); - if(T.tv_sec == 0 && T.tv_nsec == 0) return 0; - else if(T.tv_sec > 0 || (T.tv_sec==0 && T.tv_nsec > 0)) return 1; - else return -1; -} /***************************************************************************** *Function name @@ -953,11 +1350,11 @@ int timecmp(ltt_time * t1, ltt_time * t2) int getIntNumber(int size, void *evD) { - int64_t i; - if(size == 1) i = *(int8_t *)evD; - else if(size == 2) i = *(int16_t *)evD; - else if(size == 4) i = *(int32_t *)evD; - else if(size == 8) i = *(int64_t *)evD; + gint64 i; + if(size == 1) i = *(gint8 *)evD; + else if(size == 2) i = *(gint16 *)evD; + else if(size == 4) i = *(gint32 *)evD; + else if(size == 8) i = *(gint64 *)evD; return (int) i; } @@ -971,7 +1368,7 @@ int getIntNumber(int size, void *evD) * endian : endian type, little or big ****************************************************************************/ -void getDataEndianType(ltt_arch_size * size, ltt_arch_endian * endian) +void getDataEndianType(LttArchSize * size, LttArchEndian * endian) { int i = 1; char c = (char) i; @@ -991,3 +1388,34 @@ void getDataEndianType(ltt_arch_size * size, ltt_arch_endian * endian) else *size = LTT_UNKNOWN; } +/* 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; +} +