--- /dev/null
+these files are not used for the moment in the user interface. They will be added later in order to read the trace.
+
+They will be modules/plugins.
+
+Mathieu
--- /dev/null
+
+#include <lttv/lttv.h>
+
+void lttv_analyse_init() {
+
+
+}
+
+void lttv_analyse_destroy() {
+
+}
+
+
+void lttv_analyse_trace_set(lttv_trace_set *s) {
+ int i, nb;
+ lttv_hooks *before, *after;
+ lttv_attributes *a;
+
+ a = lttv_trace_set_attributes(s);
+ before = (lttv_hooks*)lttv_attributes_get_pointer_pathname(a,"hooks/before");
+ after = (lttv_hooks*)lttv_attributes_get_pointer_pathname(a,"hooks/after");
+ nb = lttv_trace_set_number(s);
+
+ lttv_hooks_call(before, s);
+ for(i = 0; i < nb; i++) {
+ lttv_analyse_trace(lttv_trace_set_get(s,i));
+ }
+ lttv_hooks_call(after, s);
+}
+
+
+void lttv_analyse_trace(lttv_trace *t) {
+ int i, nb_all_cpu, nb_per_cpu;
+ lttv_hooks *before, *after;
+ lttv_attributes *a;
+
+ a = lttv_trace_attributes(t);
+ before = (lttv_hooks*)lttv_attributes_get_pointer_pathname(a,"hooks/before");
+ after = (lttv_hooks*)lttv_attributes_get_pointer_pathname(a,"hooks/after");
+
+ nb_all_cpu = lttv_trace_tracefile_number_all_cpu(t);
+ nb_per_cpu = lttv_trace_tracefile_number_per_cpu(t);
+
+ lttv_hooks_call(before, t);
+
+ for(i = 0; i < nb_all_cpu; i++) {
+ lttv_analyse_tracefile(lttv_trace_get_all_cpu(t,i));
+ }
+
+ for(i = 0; i < nb_per_cpu; i++) {
+ lttv_analyse_tracefile(lttv_trace_get_per_cpu(t,i));
+ }
+
+ lttv_hooks_call(after, t);
+}
+
+
+void lttv_analyse_tracefile(lttv_tracefile *t) {
+ ltt_tracefile *tf;
+ ltt_event *event;
+ unsigned id;
+ lttv_hooks *before, *after, *event_hooks;
+ lttv_hooks_by_id *event_hooks_by_id;
+ lttv_attributes *a;
+
+ a = lttv_tracefile_attributes(t);
+ before = (lttv_hooks*)lttv_attributes_get_pointer_pathname(a,"hooks/before");
+ after = (lttv_hooks*)lttv_attributes_get_pointer_pathname(a,"hooks/after");
+ event_hooks = (lttv_hooks*)lttv_attributes_get_pointer_pathname(a,
+ "hooks/event");
+ event_hooks_by_id = (lttv_hooks_by_id*)
+ lttv_attributes_get_pointer_pathname(a, "hooks/eventid");
+
+ tf = lttv_tracefile_ltt_tracefile(t);
+
+ lttv_hooks_call(before, t);
+
+ if(lttv_hooks_number(hooks_event) != 0 ||
+ lttv_hooks_by_id_number(event_hook_by_id) != 0){
+ while(event = ltt_tracefile_read(tf) != NULL) {
+ lttv_hooks_call(event_hooks,event);
+ lttv_hooks_by_id_call(event_hooks_by_id,event,ltt_event_type_id(event));
+ }
+ }
+
+ lttv_hooks_call(after, t);
+
+}
+
+
--- /dev/null
+
+#include "ltt_module.h"
+
+/* This module dumps all events in a simple ascii format */
+
+static gboolean
+ ascii_dump = FALSE,
+ syscall_stats = FALSE;
+
+static gchar *dump_file = NULL;
+
+static FILE *dump_fp = stdout;
+
+struct poptOption
+ ascii_dump_option = { "ascii-dump", 'd', POPT_ARG_NONE, &ascii_dump, 0},
+ ascii_dump_option = { "dump-file", 'f', POPT_ARG_STRING, &dump_file, 0},
+ syscall_stats_option = { "syscall-stats", 's', POPT_ARG_NONE,
+ &syscall_stats, 0};
+
+static void after_options_hook(gpointer hook_data, gpointer call_data);
+
+static void before_trace_hook(gpointer hook_data, gpointer call_data);
+
+static void after_trace_hook(gpointer hook_data, gpointer call_data);
+
+static void events_hook(gpointer hook_data, gpointer call_data);
+
+void init(int argc, char **argv)
+{
+ ltt_add_command_option(&ascii_dump_option);
+ ltt_add_command_option(&syscall_stats_option);
+ ltt_add_hook(ltt_after_options_hooks,after_options_hook,NULL)
+}
+
+/* Check the command line options and insert hooks to do the work */
+
+static void after_options_hook(gpointer hook_data, gpointer call_data)
+{
+ if(ascii_dump_option || syscall_stats) {
+ ltt_add_hook(ltt_before_process_each_trace_hooks,before_trace_hook,NULL);
+ if(dump_file != NULL) {
+ dump_fp = fopen(dump_file,"w");
+ if(dump_fp == NULL) g_critical("cannot open output file %s",dump_file);
+ }
+ ltt_add_hook(ltt_after_process_each_trace_hooks,after_trace_hook,NULL);
+ }
+}
+
+/* Insert the hooks to print the events and compute and print the statistics */
+
+static unsigned *eventsCounters;
+
+struct CPUState {
+ lttProcess *current_process;
+ lttStatKey *key;
+ lttTime lastTime;
+} *CPUStates;
+
+static void before_trace_hook(gpointer hook_data, gpointer call_data) {
+ ltt_add_hook(ltt_trace_events_hooks,events_hooks,NULL);
+ fprintf(dump_fp,"Trace %s\n",(struct trace *)call_data->name);
+
+ if(ascii_dump) fprintf(dump_fp,"\nEvents\n");
+
+ /* To gather stats, register a few hooks */
+
+ if(syscall_stats) {
+ eventsCounters = g_new0(unsigned,nbEventType);
+ CPUStates = g_new0(struct CPUState, nbCPU);
+ /* initialize the state of each CPU and associated process */
+ CHECK
+ }
+}
+
+/* Print the events */
+
+static void events_hook(gpointer hook_data, gpointer call_data)
+{
+ event_struct event;
+
+ int i;
+
+ event = (struct_event *)call_data;
+
+ if(ascii_dump) {
+ fprintf(dump_fp,"\n%s.%s t=%d.%d CPU%d",event->facility_handle->name,
+ event->event_handle->name, event->time.tv_seconds,
+ event->time.tv_nanoseconds,event->CPU_id);
+
+ for(i = 0 ; i < event->base_field->nb_elements ; i++) {
+ field = event->base_field->fields + i;
+ fprintf(dump_fp," %s=",field->name);
+ switch(field->type) {
+ case INT:
+ fprintf(dump_fp,"%d",ltt_get_integer(field,event->data));
+ break;
+ case UINT:
+ fprintf(dump_fp,"%u",ltt_get_uinteger(field,event->data));
+ break;
+ case FLOAT:
+ fprintf(dump_fp,"%lg",ltt_get_float(field,event->data));
+ break;
+ case DOUBLE:
+ fprintf(dump_fp,"%g",ltt_get_double(field,event->data));
+ break;
+ case STRING:
+ fprintf(dump_fp,"%s",ltt_get_string(field,event->data));
+ break;
+ case ENUM:
+ fprintf(dump_fp,"%d",ltt_get_integer(field,event->data));
+ break;
+ case ARRAY:
+ fprintf(dump_fp,"<nested array>");
+ break;
+ case SEQUENCE:
+ fprintf(dump_fp,"<nested sequence>");
+ break;
+ case STRUCT:
+ fprintf(dump_fp,"<nested struct>");
+ break;
+ }
+ }
+ }
+
+ /* Collect statistics about each event type */
+
+ if(syscall_stats) {
+ /* Get the key for the corresponding CPU. It already contains the
+ path components for the ip, CPU, process, state, subState.
+ We add the event id and increment the statistic with that key. */
+
+ key = (GQuark *)CPUStates[event->CPUid]->key1;
+ path = key->data;
+ path[5] = eventsQuark[event->id];
+ pval = ltt_get_integer(currentStats,key);
+ (*pval)++;
+
+ /* Count the time spent in the current state. Could be done only
+ at state changes to optimize. */
+
+ key = (GQuark *)CPUStates[event->CPUid]->key2;
+ path = key->data;
+ ptime = ltt_get_time(currentStats,key);
+ (*ptime) = ltt_add_time((*ptime),ltt_sub_time(lastTime,event->time));
+ }
+}
+
+/* Specific hooks to note process and state changes, compute the following values: number of bytes read/written,
+ time elapsed, user, system, waiting, time spent in each system call,
+ name for each process. */
+
+maintain the process table, process state, last time... what we are waiting for
+
+syscall_entry_hook
+syscall_exit_hook
+trap_entry_hook
+trap_exit_hook
+irq_entry_hook
+irq_exit_hook
+sched_change_hook -> not waiting
+fork_hook -> wait fork
+wait_hook -> waiting
+wakeup_hook -> not waiting add up waiting time
+exit_hook
+exec_hook -> note file name
+open_hook -> keep track of fd/name
+close_hook -> keep track of fd
+read_hook -> bytes read, if server CPU for client...
+write_hook -> bytes written
+select_hook -> wait reason
+poll_hook -> wait reason
+mmap_hook -> keep track of fd
+munmap_hook -> keep track of fd
+setitimer_hook -> wait reason
+settimeout_hook -> wait reason
+sockcreate_hook -> client/server
+sockbind_hook -> client/server
+sockaccept_hook -> client/server
+sockconnect_hook -> client/server
+/* Close the output file and print the statistics, globally for all CPUs and
+ processes, per CPU, per process. */
+
+static void after_trace_hook(gpointer hook_data, gpointer call_data)
+{
+ lttTrace t;
+
+ unsigned nbEvents = 0;
+
+ t = (lttTrace *)call_data;
+
+ fprintf(dump_fp,"\n");
+ fclose(dump_fp);
+
+ if(syscall_stats) {
+ fprintf(dump_fp,"\n\nStatistics\n\n");
+
+ /* Trace start, end and duration */
+
+ fprintf(dump_fp,"Trace started %s, ended %s, duration %s",
+ ltt_format_time(t->startTime),ltt_format_time(t->endTime),
+ ltt_format_time(ltt_sub_time(t->endTime,t->startTime)));
+
+ /* Number of events of each type */
+
+ for(i = 0 ; i < t->nbEventTypes ; i++) {
+ nbEvents += eventsCounters[i];
+ if(eventsCounters[i] > 0)
+ fprintf(dump_fp,"%s: %u\n",t->types[i]->name,eventsCounters[i]);
+ }
+ fprintf(dump_fp,"\n\nTotal number of events: %u\n",nbEvents);
+
+ /* Print the details for each process */
+ }
+}
+
+
+
--- /dev/null
+/*
+
+Analyse: loop over events, either one tracefile after another or
+ simultaneously by increasing time over all tracefiles.
+
+Process: create the process_state structure and register for all state
+ changing events to update the process_state.
+
+Stats: create an lttv_attributes to receive statistics. Offer functions
+ to specify statistics gathering (event types, specific field as int,
+ specific field as histogram...); this is used for syscalls and for
+ bytes read and written. Eventually factor out the type of
+ state and key positions (disk state, ethernet state...)
+
+Operations on stats:
+ select based on match, sort based on compare function/key order,
+ sum based on equality of truncated key
+
+Sort order:
+ key to base the sort on, by decreasing order of preference
+
+Match/combine:
+ for each key component, accept as is, only accept x, combine with previous.
+
+Print stats:
+ print hierarchically
+
+
+*/
+
+
+typedef struct _stats_hook_data {
+ lttv_attributes *a;
+ lttv_key *key;
+ GHashTable *processes;
+ lttv_string_id current_process;
+ GArray *state;
+ lttv_string_id current_state;
+ bool init_done;
+} stats_hook_data;
+
+/* Process state is wait, user, system, trap, irq */
+
+/* before, after, print, free */
+
+/* The accumulated statistics are:
+
+for each trace:
+
+ The hierarchical key contains:
+
+ system/cpu/process/state/type/id
+
+ where state is one of user, system, irq, trap or wait, and type is one
+ of eventtype, syscall, and id is specific to each category (event id,
+ syscall number...).
+
+ print per system/state/substate/eventid (sum over process/cpu)
+ print per system/cpu/state/substate/eventid (sum over process)
+ print per system/process/state/substate/eventid (sum over cpu)
+
+ number of events of each type
+*/
+
+lttv_basicStats_before(lttv_trace_set *s)
+{
+ int i, j, nb_trace, nb_tracefile;
+ lttv_trace *t;
+ lttv_tracefile *tf;
+ lttv_attributes *a;
+ stats_hook_data *hook_data, *old;
+
+ nb_trace = lttv_trace_set_number(s);
+
+ for(i = 0 ; i < nb_trace ; i++) {
+ t = lttv_trace_set_get(s,i);
+ nb_tracefile = lttv_trace_number(t);
+
+ hook_data = lttv_basicStats_new();
+ a = lttv_trace_attributes(t);
+ old = (stats_hook_data *)lttv_attributes_get_pointer_pathname(a,
+ "stats/basic");
+ lttv_basicStats_destroy(old);
+ lttv_attributes_set_pointer_pathname(a,"stats/basic",hook_data);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tf = lttv_trace_get(t,j);
+ a = lttv_tracefile_attributes(tf);
+ h = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,"hooks/event");
+ lttv_hooks_add(h, compute_stats, hook_data);
+ }
+ }
+}
+
+lttv_basicStats_after(lttv_trace_set *s)
+{
+ int i, j, nb_trace, nb_tracefile;
+ lttv_trace *t;
+ lttv_tracefile *tf;
+ lttv_attributes *a;
+ stats_hook_data *hook_data;
+
+ nb_trace = lttv_trace_set_number(s);
+
+ for(i = 0 ; i < nb_trace ; i++) {
+ t = lttv_trace_set_get(s,i);
+ nb_tracefile = lttv_trace_number(t);
+
+ hook_data = (stats_hook_data *)lttv_attributes_get_pointer_pathname(a,
+ "stats/basic");
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tf = lttv_trace_get(t,j);
+ a = lttv_tracefile_attributes(tf);
+ h = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,"hooks/event");
+ lttv_hooks_remove(h, compute_stats, hook_data);
+ }
+
+ lttv_basicStats_destroy(hook_data);
+ }
+}
+
+
+update_state
+
+compute time in that state...
+
+For processes remember the command name...
+
+Compute bytes read/written...
+
+static void compute_eventtype_id_stats(void *hook_data, void *call_data)
+{
+ stats_hook_data *d;
+ ltt_event *e;
+
+ d = (stats_hook_data *)hook_data;
+ e = (ltt_event *)call_data;
+
+ lttv_key_index(d->key,4) = string_id_EventType;
+ lttv_key_index(d->key,5) = string_id_unsigned(ltt_event_eventtype_id(e));
+ (*lttv_attributes_get_integer(d->a,d->key))++;
+}
+
+/* The field for which a sum is required is expressed as eventtype/field */
+
+typedef struct _field_sum_data {
+ stats_hook_data *d;
+ ltt_field *f;
+ lttv_string_id type_name;
+ lttv_string_id id_name;
+} field_sum_data;
+
+lttv_basicStats_sum_integer_field_before(lttv_trace_set *s, char *field_path,
+ char *type_name, char *id_name)
+{
+ int i, j, nb_trace, nb_tracefile;
+ lttv_trace *t;
+ lttv_tracefile *tf;
+ lttv_attributes *a;
+ lttv_hooks_by_id h;
+ stats_hook_data *stats_data;
+ field_sum_data *hook_data;
+ unsigned id;
+
+ nb_trace = lttv_trace_set_number(s);
+
+ for(i = 0 ; i < nb_trace ; i++) {
+ t = lttv_trace_set_get(s,i);
+ nb_tracefile = lttv_trace_number(t);
+
+ a = lttv_trace_attributes(t);
+ stats_data = (stats_hook_data *)lttv_attributes_get_pointer_pathname(a,
+ "stats/basic");
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tf = lttv_trace_get(t,j);
+ a = lttv_tracefile_attributes(tf);
+ hook_data = g_new(field_sum_data);
+ hook_data->d = stats_data;
+ hook_data->f = lttv_tracefile_eventtype_field_pathname(
+ lttv_tracefile_ltt_tracefile(tf), field_path, &id);
+ hook_data->type_name = type_name;
+ hook_data->id_name = id_name;
+ h = (lttv_hooks_by_id *)lttv_attributes_get_pointer_pathname(a,
+ "hooks/eventid");
+ if(id_name != NULL) {
+ lttv_hooks_add(h, compute_integer_field_sum, hook_data);
+ }
+ else {
+ lttv_hooks_add(h, compute_integer_field_histogram, hook_data);
+ }
+ }
+ }
+}
+
+static void compute_integer_field_sum(void *hook_data, void *call_data)
+{
+ field_sum_data *d;
+ ltt_event *e;
+
+ d = (field_sum_data *)hook_data;
+ e = (ltt_event *)call_data;
+
+ lttv_key_index(d->key,4) = d->type_name;
+ lttv_key_index(d->key,5) = d->id_name;
+ (*lttv_attributes_get_integer(d->a,d->key)) +=
+ ltt_event_get_unsigned(e,d->f);
+}
+
+static void compute_integer_field_histogram(void *hook_data, void *call_data)
+{
+ field_sum_data *d;
+ ltt_event *e;
+
+ d = (field_sum_data *)hook_data;
+ e = (ltt_event *)call_data;
+
+ lttv_key_index(d->key,4) = d->type_name;
+ lttv_key_index(d->key,5)= string_id_unsigned(ltt_event_get_unsigned(e,d->f));
+ (*lttv_attributes_get_integer(d->a,d->key))++;
+}
+
+
+stats_hook_data *lttv_basicStats_new()
+{
+ g_new(stats_hook_data,1);
+ hook_data->a = lttv_attributes_new();
+ hook_data->key = lttv_key_new();
+ id = lttv_string_id("");
+ for j = 0 ; j < 6 ; j++) lttv_key_append(hook_data->key,id);
+ hook_data->processes = g_hash_table_new(g_int_hash,g_int_equal);
+ hook_data->init_done = FALSE;
+}
+
+stats_hook_data *lttv_basicStats_destroy(stats_hook_data *hook_data)
+{
+ lttv_attributes_destroy(hook_data->a);
+ lttv_key_destroy(hook_data->key);
+ lttv_process_state_destroy(hook_data->processes);
+ g_free(hook_data);
+ return NULL;
+}
+
+
+
--- /dev/null
+
+void lttv_event_to_string(ltt_event *e, lttv_string *s, bool mandatory_fields)
+{
+ ltt_facility *facility;
+ ltt_eventtype *eventtype;
+ ltt_type *type;
+ ltt_field *field;
+ ltt_time time;
+
+ g_string_set_size(s,0);
+
+ facility = lttv_event_facility(e);
+ eventtype = ltt_event_eventtype(e);
+ field = ltt_event_field(e);
+
+ if(mandatory_fields) {
+ time = ltt_event_time(e);
+ g_string_append_printf(s,"%s.%s: %ld.%ld",ltt_facility_name(facility),
+ ltt_eventtype_name(eventtype), (long)time.tv_sec, time.tv_nsec);
+ }
+
+ print_field(e,f,s);
+}
+
+void print_field(ltt_event *e, ltt_field *f, lttv_string *s) {
+ ltt_type *type;
+ ltt_field *element;
+
+ int nb, i;
+
+ type = ltt_field_type(f);
+ switch(ltt_type_class(type)) {
+ case LTT_INT:
+ g_string_append_printf(s, " %ld", ltt_event_get_long_int(e,f));
+ break;
+
+ case LTT_UINT:
+ g_string_append_printf(s, " %lu", ltt_event_get_long_unsigned(e,f));
+ break;
+
+ case LTT_FLOAT:
+ g_string_append_printf(s, " %g", ltt_event_get_double(e,f));
+ break;
+
+ case LTT_STRING:
+ g_string_append_printf(s, " \"%s\"", ltt_event_get_string(e,f));
+ break;
+
+ case LTT_ENUM:
+ g_string_append_printf(s, " %s", ltt_enum_string_get(type,
+ event_get_unsigned(e,f));
+ break;
+
+ case LTT_ARRAY:
+ case LTT_SEQUENCE:
+ g_string_append_printf(s, " {");
+ nb = ltt_event_field_element_number(e,f);
+ element = ltt_field_element(f);
+ for(i = 0 ; i < nb ; i++) {
+ ltt_event_field_element_select(e,f,i);
+ print_field(e,element,s);
+ }
+ g_string_append_printf(s, " }");
+ break;
+
+ case LTT_STRUCT:
+ g_string_append_printf(s, " {");
+ nb = ltt_type_member_number(type);
+ for(i = 0 ; i < nb ; i++) {
+ element = ltt_field_member(f,i);
+ print_field(e,element,s);
+ }
+ g_string_append_printf(s, " }");
+ break;
+ }
+}
+
+
+
--- /dev/null
+
+typedef struct _text_hook_data {
+ FILE *fp;
+ lttv_string *s;
+} text_hook_data;
+
+void *lttv_textDump_before(lttv_trace_set *s, FILE *fp)
+{
+ int i, j, nb_trace, nb_tracefile;
+ lttv_attributes *a;
+ lttv_hooks *h;
+ lttv_trace *t;
+ lttv_tracefile *tf;
+ text_hook_data *hook_data;
+
+ hook_data = g_new(ltt_hook_data,1);
+ nb_trace = lttv_trace_set_number(s);
+ hook_data->fp = fp;
+ hook_data->s = lttv_string_new;
+
+ for(i = 0 ; i < nb_trace ; i++) {
+ t = lttv_trace_set_get(s,i);
+ a = lttv_trace_attributes(t);
+ h = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,"hooks/before");
+ lttv_hooks_add(h, print_trace_title, hook_data);
+ nb_tracefile = lttv_trace_number(t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ h = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,"hooks/before");
+ lttv_hooks_add(h, print_tracefile_title, hook_data);
+ h = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,"hooks/event");
+ lttv_hooks_add(h, print_event, hook_data);
+ }
+ }
+}
+
+void lttv_textDump_after(lttv_trace_set *ts, void *hook_data)
+{
+ int i, j, nb_trace, nb_tracefile;
+ lttv_attributes *a;
+ lttv_hooks *h;
+ lttv_trace *t;
+ lttv_tracefile *tf;
+
+ nb_trace = lttv_trace_set_number(s);
+
+ for(i = 0 ; i < nb_trace ; i++) {
+ t = lttv_trace_set_get(s,i);
+ a = lttv_trace_attributes(t);
+ h = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,"hooks/before");
+ lttv_hooks_remove(h, print_trace_title, hook_data);
+ nb_tracefile = lttv_trace_number(t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ h = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,"hooks/before");
+ lttv_hooks_remove(h, print_tracefile_title, hook_data);
+ h = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,"hooks/event");
+ lttv_hooks_remove(h, print_event, hook_data);
+ }
+ }
+ lttv_string_destroy(hook_data->s);
+ g_free(hook_data);
+}
+
+static void print_trace_title(void *hook_data, void *call_data)
+{
+ lttv_trace *t;
+ FILE *fp;
+
+ fp = ((text_hook_data *)hook_data)->fp;
+ t = (lttv_trace *)call_data;
+ fprintf(fp,"\n\nTrace %s:\n\n" lttv_trace_name(t));
+}
+
+static void print_trace(void *hook_data, void *call_data)
+{
+ lttv_tracefile *tf;
+ FILE *fp;
+
+ fp = ((text_hook_data *)hook_data)->fp;
+ tf = (lttv_tracefile *)call_data;
+ fprintf(fp,"\n\nTracefile %s:\n\n" lttv_tracefile_name(tf));
+}
+
+static void print_event(void *hook_data, void *call_data)
+{
+ ltt_event *e;
+ FILE *fp;
+ text_hook_data *d;
+
+ d = ((text_hook_data *)hook_data;
+ e = (lttv_event *)call_data;
+ lttv_event_to_string(e,d->s,TRUE);
+ fprintf(fp,"%s\n" d->s->str);
+}
+
+
+
--- /dev/null
+/* A trace is a sequence of events gathered in the same tracing session. The
+ events may be stored in several tracefiles in the same directory.
+ A trace set is defined when several traces are to be analyzed together,
+ possibly to study the interactions between events in the different traces.
+*/
+
+struct _lttv_trace_set {
+ GPtrArray *traces;
+ lttv_attributes *a;
+};
+
+struct _lttv_trace {
+ GPtrArray *all_cpu;
+ GPtrArray *per_cpu;
+ char *name;
+ lttv_attributes *a;
+};
+
+
+struct _lttv_tracefile {
+ ltt_tracefile *t;
+ lttv_attributes *a;
+};
+
+
+lttv_trace_set *lttv_trace_set_new() {
+ lttv_trace_set s;
+
+ s = g_new(lttv_trace_set, 1);
+ s->traces = g_ptr_array_new();
+ s->a = lttv_attributes_new();
+}
+
+lttv_trace_set *lttv_trace_set_destroy(lttv_trace_set *s) {
+ g_ptr_array_free(s->traces);
+ lttv_attributes_destroy(s->a);
+ return g_free(s);
+}
+
+void lttv_trace_set_add(lttv_trace_set *s, lttv_trace *t) {
+ g_ptr_array_add(s,t);
+}
+
+unsigned lttv_trace_set_number(lttv_trace_set *s) {
+ return s->traces.len;
+}
+
+
+lttv_trace *lttv_trace_set_get(lttv_trace_set *s, unsigned i) {
+ g_assert(s->traces->len <= i);
+ return s->traces.pdata[i];
+}
+
+
+lttv_trace *lttv_trace_set_remove(lttv_trace_set *s, unsigned i) {
+ return g_ptr_array_remove_index(s->traces,i);
+}
+
+
+/* Look at all files in the directory. Open all those with ltt as extension
+ and sort these as per cpu or all cpu. */
+
+lttv_trace *lttv_trace_open(char *pathname) {
+ lttv_trace *t;
+
+ t = g_new(lttv_trace, 1);
+ t->per_cpu = g_ptr_array_new();
+ t->all_cpu = g_ptr_array_new();
+ t->a = lttv_attributes_new();
+ return t;
+}
+
+int lttv_trace_close(lttv_trace *t) {
+
+ g_ptr_array_free(t->per_cpu);
+ g_ptr_array_free(t->all_cpu);
+ lttv_attributes_destroy(t->a);
+ g_free(t);
+ return 0;
+}
+
+char *lttv_trace_name(lttv_trace *t) {
+ return t->name;
+}
+
+
+unsigned int lttv_trace_tracefile_number(lttv_trace *t) {
+ return t->per_cpu->len + t->all_cpu->len;
+}
+
+unsigned int lttv_trace_cpu_number(lttv_trace *t) {
+ /* */
+}
+
+unsigned int lttv_trace_tracefile_number_per_cpu(lttv_trace *t) {
+ return t->per_cpu->len;
+}
+
+unsigned int lttv_trace_tracefile_number_all_cpu(lttv_trace *t) {
+ return t->all_cpu_len;
+}
+
+lttv_tracefile *lttv_trace_tracefile_get_per_cpu(lttv_trace *t, unsigned i) {
+ return t->per_cpu->pdata[i];
+}
+
+lttv_tracefile *lttv_trace_tracefile_get_all_cpu(lttv_trace *t, unsigned i) {
+ return t->all_cpu->pdata[i];
+}
+
+
+/* A set of attributes is attached to each trace set, trace and tracefile
+ to store user defined data as needed. */
+
+lttv_attributes *lttv_trace_set_attributes(lttv_trace_set *s) {
+ return s->a;
+}
+
+lttv_attributes *lttv_trace_attributes(lttv_trace *t) {
+ return t->a;
+}
+
+lttv_attributes *lttv_tracefile_attributes(lttv_tracefile *tf) {
+ return tf->a;
+}
+
+
+ltt_tracefile *lttv_tracefile_ltt_tracefile(lttv_tracefile *tf) {
+ return tf->t;
+}
+
+char *lttv_tracefile_name(lttv_tracefile *tf) {
+ return tf->name;
+}
+
+