+
+ g_debug("Tracefile file or directory : %s\n", path);
+
+ if(strcmp(rel_path, "/eventdefs") == 0) continue;
+
+ if(S_ISDIR(stat_buf.st_mode)) {
+
+ g_debug("Entering subdirectory...\n");
+ ret = open_tracefiles(trace, path, rel_path);
+ if(ret < 0) continue;
+ } else if(S_ISREG(stat_buf.st_mode)) {
+ GQuark name;
+ guint num, tid, pgid;
+ guint64 creation;
+ GArray *group;
+ num = tid = pgid = 0;
+ creation = 0;
+ if(get_tracefile_name_number(rel_path, &name, &num, &tid, &pgid, &creation))
+ continue; /* invalid name */
+
+ g_debug("Opening file.\n");
+ if(ltt_tracefile_open(trace, path, &tmp_tf)) {
+ g_info("Error opening tracefile %s", path);
+
+ continue; /* error opening the tracefile : bad magic number ? */
+ }
+
+ g_debug("Tracefile name is %s and number is %u",
+ g_quark_to_string(name), num);
+
+ tmp_tf.cpu_online = 1;
+ tmp_tf.cpu_num = num;
+ tmp_tf.name = name;
+ tmp_tf.tid = tid;
+ tmp_tf.pgid = pgid;
+ tmp_tf.creation = creation;
+ if(tmp_tf.name == g_quark_from_string("/compact")
+ || tmp_tf.name == g_quark_from_string("/flight-compact"))
+ tmp_tf.compact = 1;
+ else
+ tmp_tf.compact = 0;
+ 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(&trace->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);
+ 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);