+ /* 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);
+ g_array_index (group, LttTracefile, num) = tmp_tf;
+
+ }
+ }
+
+ closedir(dir);
+
+ return 0;
+}
+
+/* ltt_get_facility_description
+ *
+ * Opens the file 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.
+ */
+#if 0
+static int ltt_get_facility_description(LttFacility *f,
+ LttTrace *t,
+ LttTracefile *fac_tf)
+{
+ char desc_file_name[PATH_MAX];
+ const gchar *text;
+ guint textlen;
+ gint err;
+ gint arch_spec;
+ gint fac_name_len;
+
+ 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);
+ fac_name_len = strlen(text);
+ textlen+=fac_name_len;
+ if(textlen >= PATH_MAX) goto name_error;
+ strcat(desc_file_name, text);
+
+ /* arch specific facilities are named like this : name_arch */
+ if(fac_name_len+1 < sizeof("_arch"))
+ arch_spec = 0;
+ else {
+ if(!strcmp(&text[fac_name_len+1-sizeof("_arch")], "_arch"))
+ arch_spec = 1;
+ else
+ arch_spec = 0;
+ }
+
+#if 0
+ 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 < 0) goto name_error;
+
+ textlen=strlen(desc_file_name);
+
+#endif //0
+
+ if(arch_spec) {
+ switch(t->arch_type) {
+ case LTT_ARCH_TYPE_I386:
+ text = "_i386";
+ break;
+ case LTT_ARCH_TYPE_PPC:
+ text = "_ppc";
+ break;
+ case LTT_ARCH_TYPE_SH:
+ text = "_sh";
+ break;
+ case LTT_ARCH_TYPE_S390:
+ text = "_s390";
+ break;
+ case LTT_ARCH_TYPE_MIPS:
+ text = "_mips";
+ break;
+ case LTT_ARCH_TYPE_ARM:
+ text = "_arm";
+ break;
+ case LTT_ARCH_TYPE_PPC64:
+ text = "_ppc64";
+ break;
+ case LTT_ARCH_TYPE_X86_64:
+ text = "_x86_64";
+ break;
+ case LTT_ARCH_TYPE_C2:
+ text = "_c2";
+ break;
+ case LTT_ARCH_TYPE_POWERPC:
+ text = "_powerpc";
+ break;
+ default:
+ g_error("Trace from unsupported architecture.");
+ }
+ textlen+=strlen(text);
+ if(textlen >= PATH_MAX) goto name_error;
+ strcat(desc_file_name, text);
+ }
+
+ 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;
+
+ return 0;
+
+facility_error:
+name_error:
+ return 1;
+}
+
+static void ltt_fac_ids_destroy(gpointer data)
+{
+ GArray *fac_ids = (GArray *)data;
+
+ g_array_free(fac_ids, TRUE);
+}
+#endif //0
+
+/* Presumes the tracefile is already seeked at the beginning. It makes sense,
+ * because it must be done just after the opening */
+int ltt_process_facility_tracefile(LttTracefile *tf)
+{
+ int err;
+ //LttFacility *fac;
+ //GArray *fac_ids;
+ guint i;
+ //LttEventType *et;
+
+ 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
+ * 3 : heartbeat
+ */
+ if(tf->event.event_id >= MARKER_CORE_IDS) {
+ /* Should only contain core facility */
+ g_warning("Error in processing facility file %s, "
+ "should not contain event id %u.", g_quark_to_string(tf->name),
+ tf->event.event_id);
+ err = EPERM;
+ goto event_id_error;
+ } else {
+
+ void *pos;
+ const char *marker_name, *format;
+ uint16_t id;
+ guint8 int_size, long_size, pointer_size, size_t_size, alignment;
+
+ // FIXME align
+ switch((enum marker_id)tf->event.event_id) {
+ case MARKER_ID_SET_MARKER_ID:
+ marker_name = (char*)(tf->event.data);
+ g_debug("Doing MARKER_ID_SET_MARKER_ID of marker %s", marker_name);
+ pos = (tf->event.data + strlen(marker_name) + 1);
+ pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment);
+ pos += ltt_align((size_t)pos, sizeof(uint16_t), tf->has_alignment);
+ id = ltt_get_uint16(LTT_GET_BO(tf), pos);
+ pos += sizeof(guint16);
+ int_size = *(guint8*)pos;
+ pos += sizeof(guint8);
+ long_size = *(guint8*)pos;
+ pos += sizeof(guint8);
+ pointer_size = *(guint8*)pos;
+ pos += sizeof(guint8);
+ size_t_size = *(guint8*)pos;
+ pos += sizeof(guint8);
+ alignment = *(guint8*)pos;
+ pos += sizeof(guint8);
+ marker_id_event(tf->trace, g_quark_from_string(marker_name),
+ id, int_size, long_size,
+ pointer_size, size_t_size, alignment);
+ break;
+ case MARKER_ID_SET_MARKER_FORMAT:
+ marker_name = (char*)(tf->event.data);
+ g_debug("Doing MARKER_ID_SET_MARKER_FORMAT of marker %s",
+ marker_name);
+ pos = (tf->event.data + strlen(marker_name) + 1);
+ pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment);
+ format = (const char*)pos;
+ pos += strlen(format) + 1;
+ pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment);
+ marker_format_event(tf->trace, g_quark_from_string(marker_name),
+ format);
+ /* get information from dictionnary TODO */
+ break;
+ case MARKER_ID_HEARTBEAT_32:
+ case MARKER_ID_HEARTBEAT_64:
+ break;
+ default:
+ g_warning("Error in processing facility file %s, "
+ "unknown event id %hhu.",
+ g_quark_to_string(tf->name),
+ tf->event.event_id);
+ err = EPERM;
+ goto event_id_error;
+ }
+ }
+ }
+ return 0;
+
+ /* Error handling */
+event_id_error:
+update_error:
+seek_error:
+ g_warning("An error occured in facility tracefile parsing");
+ return err;
+}
+
+
+LttTrace *ltt_trace_open(const gchar *pathname)
+{
+ gchar abs_path[PATH_MAX];
+ LttTrace * t;
+ LttTracefile *tf;
+ GArray *group;
+ int i, ret;
+ struct ltt_block_start_header *header;
+ DIR *dir;
+ struct dirent *entry;
+ guint control_found = 0;
+ guint eventdefs_found = 0;
+ struct stat stat_buf;
+ gchar path[PATH_MAX];
+
+ t = g_new(LttTrace, 1);
+ if(!t) goto alloc_error;
+
+ get_absolute_pathname(pathname, abs_path);
+ t->pathname = g_quark_from_string(abs_path);
+
+ g_datalist_init(&t->tracefiles);
+
+ /* Test to see if it looks like a trace */
+ dir = opendir(abs_path);
+ if(dir == NULL) {
+ perror(abs_path);
+ goto open_error;
+ }
+ while((entry = readdir(dir)) != NULL) {
+ strcpy(path, abs_path);
+ strcat(path, "/");
+ strcat(path, entry->d_name);
+ ret = stat(path, &stat_buf);
+ if(ret == -1) {
+ perror(path);
+ continue;
+ }
+ if(S_ISDIR(stat_buf.st_mode)) {
+ if(strcmp(entry->d_name, "control") == 0) {
+ control_found = 1;
+ }
+ if(strcmp(entry->d_name, "eventdefs") == 0) {
+ eventdefs_found = 1;
+ }
+ }
+ }
+ closedir(dir);
+
+ if(!control_found || !eventdefs_found) goto find_error;
+
+ /* Open all the tracefiles */
+ if(open_tracefiles(t, abs_path, "")) {
+ g_warning("Error opening tracefile %s", abs_path);
+ goto find_error;
+ }
+
+ /* Parse each trace control/facilitiesN files : get runtime fac. info */
+ 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;
+ }
+
+ /* Get the trace information for the control/facility 0 tracefile */
+ g_assert(group->len > 0);
+ tf = &g_array_index (group, LttTracefile, 0);
+ header = (struct ltt_block_start_header*)tf->buffer.head;
+ g_assert(parse_trace_header(header->trace,
+ tf, t) == 0);
+
+ t->num_cpu = group->len;
+
+ for(i=0; i<group->len; 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_clear(&t->facilities_by_name);
+ g_array_free(t->facilities_by_num, TRUE);
+find_error:
+ g_datalist_clear(&t->tracefiles);
+open_error:
+ g_free(t);
+alloc_error:
+ return NULL;
+
+}
+
+GQuark ltt_trace_name(const 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(g_quark_to_string(self->pathname));
+}
+
+void ltt_trace_close(LttTrace *t)
+{
+ g_datalist_clear(&t->tracefiles);
+ g_free(t);
+}
+
+
+/*****************************************************************************
+ *Get the system description of the trace
+ ****************************************************************************/
+#if 0
+LttFacility *ltt_trace_facility_by_id(LttTrace *t, guint8 id)
+{
+ g_assert(id < 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);
+}
+#endif //0
+
+/*****************************************************************************
+ * 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;i<num;i++){
+ f = (LttFacility*)g_ptr_array_index(t->facilities, 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