From: compudj Date: Tue, 27 Jan 2004 21:03:52 +0000 (+0000) Subject: directory change, part 1 X-Git-Tag: v0.12.20~3090 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=fcdf74b2f0f101853545898193bcc2f6eb02c85d;p=lttv.git directory change, part 1 git-svn-id: http://ltt.polymtl.ca/svn@399 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/ltt/branches/poly/lttv/Makefile.am b/ltt/branches/poly/lttv/Makefile.am deleted file mode 100644 index c91d0138..00000000 --- a/ltt/branches/poly/lttv/Makefile.am +++ /dev/null @@ -1,26 +0,0 @@ -AM_CFLAGS = $(GLIB_CFLAGS) -LIBS += $(GLIB_LIBS) -lgobject-2.0 -L$(top_srcdir)/ltt -ltraceread -#LIBS += $(GLIB_LIBS) -lgobject-2.0 -lltt - -bin_PROGRAMS = lttv - -#AM_CPPFLAGS = \ -# -I$(top_srcdir)/include -#INCLUDES=$(top_srcdir)/include - -lttv_SOURCES = main.c module.c option.c hook.c attribute.c \ - iattribute.c processTrace.c state.c stats.c traceset.c - -libdir = ${lttvplugindir} - -lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la -libtextDump_la_LDFLAGS = -module -libtextDump_la_SOURCES = textDump.c -libbatchAnalysis_la_LDFLAGS = -module -libbatchAnalysis_la_SOURCES = batchAnalysis.c - - -# WARNING : must be done at the end, so modules can dynamically link themselves -# to libraries compiled here but not installed in the system. -SUBDIRS = modules - diff --git a/ltt/branches/poly/lttv/README b/ltt/branches/poly/lttv/README index 6b36fd32..8e71c628 100644 --- a/ltt/branches/poly/lttv/README +++ b/ltt/branches/poly/lttv/README @@ -15,3 +15,9 @@ would be (if the installation prefix is /usr, for instance) lttv -L /usr/lib/lttv/plugins -m mainwin -m guiEvents +* Tree structure +main: main program +mainLib: libraries acting as core of the interaction between main program + and modules. +modules: text and graphical viewing and analysis tools. + diff --git a/ltt/branches/poly/lttv/attribute.c b/ltt/branches/poly/lttv/attribute.c deleted file mode 100644 index 4b6938d7..00000000 --- a/ltt/branches/poly/lttv/attribute.c +++ /dev/null @@ -1,383 +0,0 @@ - -#include -#include - -typedef union _AttributeValue { - int dv_int; - unsigned dv_uint; - long dv_long; - unsigned long dv_ulong; - float dv_float; - double dv_double; - LttTime dv_time; - gpointer dv_pointer; - char *dv_string; - GObject *dv_gobject; -} AttributeValue; - - -typedef struct _Attribute { - LttvAttributeName name; - LttvAttributeType type; - AttributeValue value; -} Attribute; - - -LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v) -{ - LttvAttributeValue va; - - switch(t) { - case LTTV_INT: va.v_int = &v->dv_int; break; - case LTTV_UINT: va.v_uint = &v->dv_uint; break; - case LTTV_LONG: va.v_long = &v->dv_long; break; - case LTTV_ULONG: va.v_ulong = &v->dv_ulong; break; - case LTTV_FLOAT: va.v_float = &v->dv_float; break; - case LTTV_DOUBLE: va.v_double = &v->dv_double; break; - case LTTV_TIME: va.v_time = &v->dv_time; break; - case LTTV_POINTER: va.v_pointer = &v->dv_pointer; break; - case LTTV_STRING: va.v_string = &v->dv_string; break; - case LTTV_GOBJECT: va.v_gobject = &v->dv_gobject; break; - } - return va; -} - - -AttributeValue init_value(LttvAttributeType t) -{ - AttributeValue v; - - switch(t) { - case LTTV_INT: v.dv_int = 0; break; - case LTTV_UINT: v.dv_uint = 0; break; - case LTTV_LONG: v.dv_long = 0; break; - case LTTV_ULONG: v.dv_ulong = 0; break; - case LTTV_FLOAT: v.dv_float = 0; break; - case LTTV_DOUBLE: v.dv_double = 0; break; - case LTTV_TIME: v.dv_time.tv_sec = 0; v.dv_time.tv_nsec = 0; break; - case LTTV_POINTER: v.dv_pointer = NULL; break; - case LTTV_STRING: v.dv_string = NULL; break; - case LTTV_GOBJECT: v.dv_gobject = NULL; break; - } - return v; -} - - -unsigned int -lttv_attribute_get_number(LttvAttribute *self) -{ - return self->attributes->len; -} - - -gboolean -lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous) -{ - *homogeneous = FALSE; - return TRUE; -} - - -LttvAttributeType -lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name, - LttvAttributeValue *v) -{ - Attribute *a; - - a = &g_array_index(self->attributes, Attribute, i); - *name = a->name; - *v = address_of_value(a->type, &(a->value)); - return a->type; -} - - -LttvAttributeType -lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name, - LttvAttributeValue *v) -{ - Attribute *a; - - unsigned i; - - gpointer p; - - p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); - if(p == NULL) return LTTV_NONE; - - i = GPOINTER_TO_UINT(p); - i--; - a = &g_array_index(self->attributes, Attribute, i); - *v = address_of_value(a->type, &(a->value)); - return a->type; -} - - -LttvAttributeValue -lttv_attribute_add(LttvAttribute *self, LttvAttributeName name, - LttvAttributeType t) -{ - unsigned i; - - Attribute a, *pa; - - i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); - if(i != 0) g_error("duplicate entry in attribute table"); - - a.name = name; - a.type = t; - a.value = init_value(t); - g_array_append_val(self->attributes, a); - i = self->attributes->len - 1; - pa = &g_array_index(self->attributes, Attribute, i); - g_hash_table_insert(self->names, GUINT_TO_POINTER(name), - GUINT_TO_POINTER(i + 1)); - return address_of_value(t, &(pa->value)); -} - - -/* Remove an attribute */ - -void -lttv_attribute_remove(LttvAttribute *self, unsigned i) -{ - Attribute *a; - - a = &g_array_index(self->attributes, Attribute, i); - - /* Remove the array element and its entry in the name index */ - - g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name)); - g_array_remove_index_fast(self->attributes, i); - - /* The element used to replace the removed element has its index entry - all wrong now. Reinsert it with its new position. */ - - if(self->attributes->len != i){ - g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name)); - g_hash_table_insert(self->names, GUINT_TO_POINTER(a->name), GUINT_TO_POINTER(i + 1)); - } -} - -void -lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name) -{ - unsigned i; - - i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); - if(i == 0) g_error("remove by name non existent attribute"); - - lttv_attribute_remove(self, i - 1); -} - -/* Create an empty iattribute object and add it as an attribute under the - specified name, or return an existing iattribute attribute. If an - attribute of that name already exists but is not a GObject supporting the - iattribute interface, return NULL. */ - -/*CHECK*/LttvAttribute* -lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name) -{ - unsigned i; - - Attribute a; - - LttvAttribute *new; - - i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); - if(i != 0) { - a = g_array_index(self->attributes, Attribute, i - 1); - if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) { - return LTTV_ATTRIBUTE(a.value.dv_gobject); - } - else return NULL; - } - new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new); - return (LttvAttribute *)new; -} - -gboolean -lttv_attribute_find(LttvAttribute *self, LttvAttributeName name, - LttvAttributeType t, LttvAttributeValue *v) -{ - unsigned i; - - Attribute *a; - - i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); - if(i != 0) { - a = &g_array_index(self->attributes, Attribute, i - 1); - if(a->type != t) return FALSE; - *v = address_of_value(t, &(a->value)); - return TRUE; - } - - *v = lttv_attribute_add(self, name, t); - return TRUE; -} - - -void lttv_attribute_recursive_free(LttvAttribute *self) -{ - int i, nb; - - Attribute *a; - - nb = self->attributes->len; - - for(i = 0 ; i < nb ; i++) { - a = &g_array_index(self->attributes, Attribute, i); - if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) { - lttv_attribute_recursive_free((LttvAttribute *)(a->value.dv_gobject)); - } - } - g_object_unref(self); -} - - -void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src) -{ - int i, nb; - - Attribute *a; - - LttvAttributeValue value; - - nb = src->attributes->len; - - for(i = 0 ; i < nb ; i++) { - a = &g_array_index(src->attributes, Attribute, i); - if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) { - lttv_attribute_recursive_add( - /*CHECK*/(LttvAttribute *)lttv_attribute_find_subdir(dest, a->name), - (LttvAttribute *)(a->value.dv_gobject)); - } - else { - g_assert(lttv_attribute_find(dest, a->name, a->type, &value)); - switch(a->type) { - case LTTV_INT: - *value.v_int += a->value.dv_int; - break; - case LTTV_UINT: - *value.v_uint += a->value.dv_uint; - break; - case LTTV_LONG: - *value.v_long += a->value.dv_long; - break; - case LTTV_ULONG: - *value.v_ulong += a->value.dv_ulong; - break; - case LTTV_FLOAT: - *value.v_float += a->value.dv_float; - break; - case LTTV_DOUBLE: - *value.v_double += a->value.dv_double; - break; - case LTTV_TIME: - *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time); - break; - case LTTV_POINTER: - break; - case LTTV_STRING: - break; - case LTTV_GOBJECT: - break; - case LTTV_NONE: - break; - } - } - } -} - - -static void -attribute_interface_init (gpointer g_iface, gpointer iface_data) -{ - LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface; - - klass->get_number = (unsigned int (*) (LttvIAttribute *self)) - lttv_attribute_get_number; - - klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous)) - lttv_attribute_named; - - klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i, - LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get; - - klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self, - LttvAttributeName name, LttvAttributeValue *v)) - lttv_attribute_get_by_name; - - klass->add = (LttvAttributeValue (*) (LttvIAttribute *self, - LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add; - - klass->remove = (void (*) (LttvIAttribute *self, unsigned i)) - lttv_attribute_remove; - - klass->remove_by_name = (void (*) (LttvIAttribute *self, - LttvAttributeName name)) lttv_attribute_remove_by_name; - - klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self, - LttvAttributeName name)) lttv_attribute_find_subdir; -} - - -static void -attribute_instance_init (GTypeInstance *instance, gpointer g_class) -{ - LttvAttribute *self = (LttvAttribute *)instance; - self->names = g_hash_table_new(g_direct_hash, g_direct_equal); - self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute)); -} - - -static void -attribute_finalize (LttvAttribute *self) -{ - g_hash_table_destroy(self->names); - g_critical("attribute_finalize()"); - g_array_free(self->attributes, TRUE); - G_OBJECT_CLASS(g_type_class_peek_parent( - g_type_class_peek(LTTV_ATTRIBUTE_TYPE)))->finalize(G_OBJECT(self)); -} - - -static void -attribute_class_init (LttvAttributeClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self))attribute_finalize; -} - -GType -lttv_attribute_get_type (void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvAttributeClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) attribute_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvAttribute), - 0, /* n_preallocs */ - (GInstanceInitFunc) attribute_instance_init /* instance_init */ - }; - - static const GInterfaceInfo iattribute_info = { - (GInterfaceInitFunc) attribute_interface_init, /* interface_init */ - NULL, /* interface_finalize */ - NULL /* interface_data */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info, - 0); - g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info); - } - return type; -} - - diff --git a/ltt/branches/poly/lttv/batchAnalysis.c b/ltt/branches/poly/lttv/batchAnalysis.c deleted file mode 100644 index 62703429..00000000 --- a/ltt/branches/poly/lttv/batchAnalysis.c +++ /dev/null @@ -1,182 +0,0 @@ -/* This module inserts a hook in the program main loop. This hook processes - all the events in the main tracefile. */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static LttvTraceset *traceset; - -static LttvHooks - *before_traceset, - *after_traceset, - *before_trace, - *after_trace, - *before_tracefile, - *after_tracefile, - *before_event, - *after_event, - *main_hooks; - -static char *a_trace; - -static gboolean a_stats; - -void lttv_trace_option(void *hook_data) -{ - LttTrace *trace; - - trace = ltt_trace_open(a_trace); - if(trace == NULL) g_critical("cannot open trace %s", a_trace); - lttv_traceset_add(traceset, lttv_trace_new(trace)); -} - - -static gboolean process_traceset(void *hook_data, void *call_data) -{ - LttvTracesetStats *tscs; - - LttvTracesetContext *tc; - - LttTime start, end; - - g_info("BatchAnalysis begin process traceset"); - - tscs = g_object_new(LTTV_TRACESET_STATS_TYPE, NULL); - tc = &tscs->parent.parent; - - g_info("BatchAnalysis initialize context"); - - lttv_context_init(tc, traceset); - lttv_state_add_event_hooks(&tscs->parent); - if(a_stats) lttv_stats_add_event_hooks(tscs); - - lttv_traceset_context_add_hooks(tc, - before_traceset, after_traceset, NULL, before_trace, after_trace, - NULL, before_tracefile, after_tracefile, NULL, before_event, after_event); - - start.tv_sec = 0; - start.tv_nsec = 0; - end.tv_sec = G_MAXULONG; - end.tv_nsec = G_MAXULONG; - - g_info("BatchAnalysis process traceset"); - - lttv_process_traceset_seek_time(tc, start); - lttv_process_traceset(tc, end, G_MAXULONG); - - g_info("BatchAnalysis destroy context"); - - lttv_traceset_context_remove_hooks(tc, - before_traceset, after_traceset, NULL, before_trace, after_trace, - NULL, before_tracefile, after_tracefile, NULL, before_event, after_event); - lttv_state_remove_event_hooks(&tscs->parent); - if(a_stats) lttv_stats_remove_event_hooks(tscs); - lttv_context_fini(tc); - g_object_unref(tscs); - - g_info("BatchAnalysis end process traceset"); -} - - -G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv) -{ - LttvAttributeValue value; - - LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); - - g_info("Init batchAnalysis.c"); - - lttv_option_add("trace", 't', - "add a trace to the trace set to analyse", - "pathname of the directory containing the trace", - LTTV_OPT_STRING, &a_trace, lttv_trace_option, NULL); - - a_stats = FALSE; - lttv_option_add("stats", 's', - "write the traceset and trace statistics", - "", - LTTV_OPT_NONE, &a_stats, NULL, NULL); - - - traceset = lttv_traceset_new(); - - before_traceset = lttv_hooks_new(); - after_traceset = lttv_hooks_new(); - before_trace = lttv_hooks_new(); - after_trace = lttv_hooks_new(); - before_tracefile = lttv_hooks_new(); - after_tracefile = lttv_hooks_new(); - before_event = lttv_hooks_new(); - after_event = lttv_hooks_new(); - - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/before", - LTTV_POINTER, &value)); - *(value.v_pointer) = before_traceset; - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/after", - LTTV_POINTER, &value)); - *(value.v_pointer) = after_traceset; - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/before", - LTTV_POINTER, &value)); - *(value.v_pointer) = before_trace; - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/after", - LTTV_POINTER, &value)); - *(value.v_pointer) = after_trace; - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/before", - LTTV_POINTER, &value)); - *(value.v_pointer) = before_tracefile; - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/after", - LTTV_POINTER, &value)); - *(value.v_pointer) = after_tracefile; - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/before", - LTTV_POINTER, &value)); - *(value.v_pointer) = before_event; - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/after", - LTTV_POINTER, &value)); - *(value.v_pointer) = after_event; - - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/before", - LTTV_POINTER, &value)); - g_assert((main_hooks = *(value.v_pointer)) != NULL); - lttv_hooks_add(main_hooks, process_traceset, NULL); -} - - -G_MODULE_EXPORT void destroy() -{ - guint i, nb; - - LttvTrace *trace; - - g_info("Destroy batchAnalysis.c"); - - lttv_option_remove("trace"); - lttv_option_remove("stats"); - - lttv_hooks_destroy(before_traceset); - lttv_hooks_destroy(after_traceset); - lttv_hooks_destroy(before_trace); - lttv_hooks_destroy(after_trace); - lttv_hooks_destroy(before_tracefile); - lttv_hooks_destroy(after_tracefile); - lttv_hooks_destroy(before_event); - lttv_hooks_destroy(after_event); - lttv_hooks_remove_data(main_hooks, process_traceset, NULL); - - nb = lttv_traceset_number(traceset); - for(i = 0 ; i < nb ; i++) { - trace = lttv_traceset_get(traceset, i); - ltt_trace_close(lttv_trace(trace)); - lttv_trace_destroy(trace); - } - - lttv_traceset_destroy(traceset); -} - diff --git a/ltt/branches/poly/lttv/filter.c b/ltt/branches/poly/lttv/filter.c deleted file mode 100644 index c63940ba..00000000 --- a/ltt/branches/poly/lttv/filter.c +++ /dev/null @@ -1,58 +0,0 @@ - - consist in AND, OR and NOT nested expressions, forming a tree with - simple relations as leaves. The simple relations test is a field - in an event is equal, not equal, smaller, smaller or equal, larger, or - larger or equal to a specified value. */ - -typedef enum _lttv_expression_op -{ LTTV_FIELD_EQ, - LTTV_FIELD_NE, - LTTV_FIELD_LT, - LTTV_FIELD_LE, - LTTV_FIELD_GT, - LTTV_FIELD_GE -} lttv_expression_op; - -typedef _lttv_simple_expression -{ lttv_expression_op op; - char *field_name; - char *value; -} lttv_simple_expression; - -typedef _lttv_expression_type -{ LTTV_EXPRESSION, - LTTV_SIMPLE_EXPRESSION - -} -typedef struct _lttv_expression -{ bool or; - bool not; - bool simple_expression; - union - { lttv_expression *e; - lttv_field_relation *se; - } e; -} lttv_expression; - -read_token - -read_expression - ( read expr ) - simple expr [ op expr ] - -read_simple_expression - read_field_path [ rel value ] - -read_field_path - read_field_component [. field path] - -read_field_component - name [ \[ value \] ] - -data struct: -and/or(left/right) -not(child) -op(left/right) -path(component...) -> field - - diff --git a/ltt/branches/poly/lttv/hook.c b/ltt/branches/poly/lttv/hook.c deleted file mode 100644 index 8edbb2af..00000000 --- a/ltt/branches/poly/lttv/hook.c +++ /dev/null @@ -1,212 +0,0 @@ - -#include - - -typedef struct _LttvHookClosure { - LttvHook hook; - void *hook_data; -} LttvHookClosure; - - -LttvHooks *lttv_hooks_new() -{ - return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure)); -} - - -void lttv_hooks_destroy(LttvHooks *h) -{ - g_critical("lttv_hooks_destroy()"); - g_array_free(h, TRUE); -} - - -void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data) -{ - LttvHookClosure c; - - if(h == NULL)g_error("Null hook added"); - - c.hook = f; - c.hook_data = hook_data; - g_array_append_val(h,c); -} - - -void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list) -{ - guint i; - - if(list == NULL) return; - for(i = 0 ; i < list->len; i++) { - g_array_append_val(h,g_array_index(list, LttvHookClosure, i)); - } -} - - -void *lttv_hooks_remove(LttvHooks *h, LttvHook f) -{ - unsigned i; - - void *hook_data; - - LttvHookClosure *c; - - for(i = 0 ; i < h->len ; i++) { - c = &g_array_index(h, LttvHookClosure, i); - if(c->hook == f) { - hook_data = c->hook_data; - lttv_hooks_remove_by_position(h, i); - return hook_data; - } - } - return NULL; -} - - -void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data) -{ - unsigned i; - - LttvHookClosure *c; - - for(i = 0 ; i < h->len ; i++) { - c = &g_array_index(h, LttvHookClosure, i); - if(c->hook == f && c->hook_data == hook_data) { - lttv_hooks_remove_by_position(h, i); - return; - } - } -} - - -void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list) -{ - guint i, j; - - LttvHookClosure *c, *c_list; - - if(list == NULL) return; - for(i = 0, j = 0 ; i < h->len && j < list->len ;) { - c = &g_array_index(h, LttvHookClosure, i); - c_list = &g_array_index(list, LttvHookClosure, j); - if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) { - lttv_hooks_remove_by_position(h, i); - j++; - } - else i++; - } - - /* Normally the hooks in h are ordered as in list. If this is not the case, - try harder here. */ - - if(j < list->len) { - for(; j < list->len ; j++) { - c_list = &g_array_index(list, LttvHookClosure, j); - lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data); - } - } -} - - -unsigned lttv_hooks_number(LttvHooks *h) -{ - return h->len; -} - - -void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data) -{ - LttvHookClosure *c; - - c = &g_array_index(h, LttvHookClosure, i); - *f = c->hook; - *hook_data = c->hook_data; -} - - -void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i) -{ - g_array_remove_index(h, i); -} - - -gboolean lttv_hooks_call(LttvHooks *h, void *call_data) -{ - gboolean ret, sum_ret = FALSE; - - LttvHookClosure *c; - - guint i; - - if(h != NULL) { - for(i = 0 ; i < h->len ; i++) { - c = &g_array_index(h, LttvHookClosure, i); - ret = c->hook(c->hook_data,call_data); - sum_ret = sum_ret || ret; - } - } - return sum_ret; -} - - -gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data) -{ - LttvHookClosure *c; - - guint i; - - for(i = 0 ; i < h->len ; i++) { - c = &g_array_index(h, LttvHookClosure, i); - if(c->hook(c->hook_data,call_data)) return TRUE; - } - return FALSE; -} - - -LttvHooksById *lttv_hooks_by_id_new() -{ - return g_ptr_array_new(); -} - - -void lttv_hooks_by_id_destroy(LttvHooksById *h) -{ - guint i; - - for(i = 0 ; i < h->len ; i++) { - if(h->pdata[i] != NULL) lttv_hooks_destroy((LttvHooks *)(h->pdata[i])); - } - g_ptr_array_free(h, TRUE); -} - - -LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id) -{ - if(h->len <= id) g_ptr_array_set_size(h, id + 1); - if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new(); - return h->pdata[id]; -} - - -unsigned lttv_hooks_by_id_max_id(LttvHooksById *h) -{ - return h->len; -} - - -LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id) -{ - if(id < h->len) return h->pdata[id]; - return NULL; -} - - -void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id) -{ - if(id < h->len && h->pdata[id] != NULL) { - lttv_hooks_destroy((LttvHooks *)h->pdata[id]); - h->pdata[id] = NULL; - } -} - diff --git a/ltt/branches/poly/lttv/iattribute.c b/ltt/branches/poly/lttv/iattribute.c deleted file mode 100644 index e39d7e08..00000000 --- a/ltt/branches/poly/lttv/iattribute.c +++ /dev/null @@ -1,260 +0,0 @@ - -#include - -static void -lttv_iattribute_base_init (gpointer klass) -{ - static gboolean initialized = FALSE; - - if (!initialized) { - initialized = TRUE; - } -} - - -GType -lttv_iattribute_get_type (void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvIAttributeClass), - lttv_iattribute_base_init, /* base_init */ - NULL, /* base_finalize */ - NULL, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - 0, - 0, /* n_preallocs */ - NULL /* instance_init */ - }; - type = g_type_register_static (G_TYPE_INTERFACE, "LttvIAttribute", - &info, 0); - } - return type; -} - - -unsigned int lttv_iattribute_get_number(LttvIAttribute *self) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->get_number (self); -} - - -gboolean lttv_iattribute_named(LttvIAttribute *self, gboolean *homogeneous) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->named (self, homogeneous); -} - - -LttvAttributeType lttv_iattribute_get(LttvIAttribute *self, unsigned i, - LttvAttributeName *name, LttvAttributeValue *v) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->get (self, i, name, v); -} - - -LttvAttributeType lttv_iattribute_get_by_name(LttvIAttribute *self, - LttvAttributeName name, LttvAttributeValue *v) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->get_by_name (self, name, v); -} - - -LttvAttributeValue lttv_iattribute_add(LttvIAttribute *self, - LttvAttributeName name, LttvAttributeType t) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->add (self, name, t); -} - - -void lttv_iattribute_remove(LttvIAttribute *self, unsigned i) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->remove (self, i); -} - - -void lttv_iattribute_remove_by_name(LttvIAttribute *self, - LttvAttributeName name) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->remove_by_name (self, name); -} - -LttvIAttribute* lttv_iattribute_find_subdir(LttvIAttribute *self, - LttvAttributeName name) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->find_subdir (self, name); -} - - -/* Find the named attribute in the table, which must be of the specified type. - If it does not exist, it is created with a default value of 0 (NULL for - pointer types). Since the address of the value is obtained, it may be - changed easily afterwards. The function returns false when the attribute - exists but is of incorrect type. */ - -gboolean lttv_iattribute_find(LttvIAttribute *self, LttvAttributeName name, - LttvAttributeType t, LttvAttributeValue *v) -{ - LttvAttributeType found_type; - - found_type = lttv_iattribute_get_by_name(self, name, v); - if(found_type == t) return TRUE; - - if(found_type == LTTV_NONE) { - *v = lttv_iattribute_add(self, name, t); - return TRUE; - } - - return FALSE; -} - - -/* Trees of attribute tables may be accessed using a hierarchical path with - components separated by /, like in filesystems */ - -gboolean lttv_iattribute_find_by_path(LttvIAttribute *self, char *path, - LttvAttributeType t, LttvAttributeValue *v) -{ - LttvIAttribute *node = self; - - LttvAttributeType found_type; - - LttvAttributeName name; - - gchar **components, **cursor; - - components = g_strsplit(path, "\"", G_MAXINT); - - if(components == NULL || *components == NULL) { - g_strfreev(components); - return FALSE; - } - - for(cursor = components;;) { - name = g_quark_from_string(*cursor); - cursor++; - - if(*cursor == NULL) { - g_strfreev(components); - return lttv_iattribute_find(node, name, t, v); - } - else { - found_type = lttv_iattribute_get_by_name(node, name, v); - if(found_type == LTTV_NONE) { - node = lttv_iattribute_find_subdir(node, name); - } - else if(found_type == LTTV_GOBJECT && - LTTV_IS_IATTRIBUTE(*(v->v_gobject))) { - node = LTTV_IATTRIBUTE(*(v->v_gobject)); - } - else { - g_strfreev(components); - return FALSE; - } - } - } -} - -/* Shallow and deep copies */ - -LttvIAttribute *lttv_iattribute_shallow_copy(LttvIAttribute *self) -{ - LttvIAttribute *copy; - - LttvAttributeType t; - - LttvAttributeValue v, v_copy; - - LttvAttributeName name; - - int i; - - int nb_attributes = lttv_iattribute_get_number(self); - - copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self),NULL)); - - for(i = 0 ; i < nb_attributes ; i++) { - t = lttv_iattribute_get(self, i, &name, &v); - v_copy = lttv_iattribute_add(copy, name, t); - lttv_iattribute_copy_value(t, v_copy, v); - } -} - -LttvIAttribute *lttv_iattribute_deep_copy(LttvIAttribute *self) -{ - LttvIAttribute *copy, *child; - - LttvAttributeType t; - - LttvAttributeValue v, v_copy; - - LttvAttributeName name; - - int i; - - int nb_attributes = lttv_iattribute_get_number(self); - - copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self), NULL)); - - for(i = 0 ; i < nb_attributes ; i++) { - t = lttv_iattribute_get(self, i, &name, &v); - v_copy = lttv_iattribute_add(copy, name, t); - if(t == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(*(v.v_gobject))) { - child = LTTV_IATTRIBUTE(*(v.v_gobject)); - *(v_copy.v_gobject) = G_OBJECT(lttv_iattribute_deep_copy(child)); - } - else lttv_iattribute_copy_value(t, v_copy, v); - } -} - -void lttv_iattribute_copy_value(LttvAttributeType t, LttvAttributeValue dest, - LttvAttributeValue src) -{ - switch(t) { - case LTTV_INT: - *(dest.v_int) = *(src.v_int); - break; - - case LTTV_UINT: - *(dest.v_uint) = *(src.v_uint); - break; - - case LTTV_LONG: - *(dest.v_long) = *(src.v_long); - break; - - case LTTV_ULONG: - *(dest.v_ulong) = *(src.v_ulong); - break; - - case LTTV_FLOAT: - *(dest.v_float) = *(src.v_float); - break; - - case LTTV_DOUBLE: - *(dest.v_double) = *(src.v_double); - break; - - case LTTV_TIME: - *(dest.v_time) = *(src.v_time); - break; - - case LTTV_POINTER: - *(dest.v_pointer) = *(src.v_pointer); - break; - - case LTTV_STRING: - *(dest.v_string) = *(src.v_string); - break; - - case LTTV_GOBJECT: - *(dest.v_gobject) = *(src.v_gobject); - break; - - case LTTV_NONE: - break; - } -} - - diff --git a/ltt/branches/poly/lttv/main.c b/ltt/branches/poly/lttv/main.c deleted file mode 100644 index 7b6f7153..00000000 --- a/ltt/branches/poly/lttv/main.c +++ /dev/null @@ -1,221 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -void lttv_option_init(int argc, char **argv); -void lttv_option_destroy(); - -void lttv_module_init(int argc, char **argv); -void lttv_module_destroy(); - -void lttv_state_init(int argc, char **argv); -void lttv_state_destroy(); - -void lttv_stats_init(int argc, char **argv); -void lttv_stats_destroy(); - -/* The main program maintains a few central data structures and relies - on modules for the rest. These data structures may be accessed by modules - through an exported API */ - -static LttvIAttribute *attributes; - -static LttvHooks - *before_options, - *after_options, - *before_main, - *after_main; - -static char - *a_module, - *a_module_path; - -static gboolean - a_verbose, - a_debug; - -static int a_argc; - -static char **a_argv; - -static void lttv_module_option(void *hook_data); - -static void lttv_module_path_option(void *hook_data); - -static void lttv_verbose(void *hook_data); - -static void lttv_debug(void *hook_data); - -static void lttv_help(void *hook_data); - -/* Since everything is done in modules, the main program only takes care - of the infrastructure. */ - -int main(int argc, char **argv) { - - LttvAttributeValue value; - -#ifdef MEMDEBUG - g_mem_set_vtable(glib_mem_profiler_table); - g_message("Memory summary before main"); - g_mem_profile(); -#endif - - g_type_init(); - //g_type_init_with_debug_flags (G_TYPE_DEBUG_OBJECTS | G_TYPE_DEBUG_SIGNALS); - - attributes = LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE, NULL)); - - before_options = lttv_hooks_new(); - after_options = lttv_hooks_new(); - before_main = lttv_hooks_new(); - after_main = lttv_hooks_new(); - - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/options/before", - LTTV_POINTER, &value)); - *(value.v_pointer) = before_options; - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/options/after", - LTTV_POINTER, &value)); - *(value.v_pointer) = after_options; - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/before", - LTTV_POINTER, &value)); - *(value.v_pointer) = before_main; - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/after", - LTTV_POINTER, &value)); - *(value.v_pointer) = after_main; - - - /* Initialize the command line options processing */ - - a_argc = argc; - a_argv = argv; - lttv_option_init(argc,argv); - lttv_module_init(argc,argv); - lttv_state_init(argc,argv); - lttv_stats_init(argc,argv); - - /* Initialize the module loading */ - - lttv_module_path_add("/usr/lib/lttv/plugins"); - - /* Add some built-in options */ - - lttv_option_add("module",'m', "load a module", "name of module to load", - LTTV_OPT_STRING, &a_module, lttv_module_option, NULL); - - lttv_option_add("modules-path", 'L', - "add a directory to the module search path", - "directory to add to the path", LTTV_OPT_STRING, &a_module_path, - lttv_module_path_option, NULL); - - lttv_option_add("help",'h', "basic help", "none", - LTTV_OPT_NONE, NULL, lttv_help, NULL); - - a_verbose = FALSE; - lttv_option_add("verbose",'v', "print information messages", "none", - LTTV_OPT_NONE, NULL, lttv_verbose, NULL); - - a_debug = FALSE; - lttv_option_add("debug",'d', "print debugging messages", "none", - LTTV_OPT_NONE, NULL, lttv_debug, NULL); - - - lttv_hooks_call(before_options, NULL); - lttv_option_parse(argc, argv); - lttv_hooks_call(after_options, NULL); - - lttv_hooks_call(before_main, NULL); - lttv_hooks_call(after_main, NULL); - - lttv_stats_destroy(); - lttv_state_destroy(); - lttv_module_destroy(); - lttv_option_destroy(); - - lttv_hooks_destroy(before_options); - lttv_hooks_destroy(after_options); - lttv_hooks_destroy(before_main); - lttv_hooks_destroy(after_main); - g_object_unref(attributes); - -#ifdef MEMDEBUG - g_message("Memory summary after main"); - g_mem_profile(); -#endif -} - - -LttvAttribute *lttv_global_attributes() -{ - return (LttvAttribute*)attributes; -} - - -void lttv_module_option(void *hook_data) -{ - lttv_module_load(a_module,a_argc,a_argv); -} - - -void lttv_module_path_option(void *hook_data) -{ - lttv_module_path_add(a_module_path); -} - -void lttv_verbose(void *hook_data) -{ - g_log_set_handler(NULL, G_LOG_LEVEL_INFO, g_log_default_handler, NULL); - g_info("Logging set to include INFO level messages"); -} - -void lttv_debug(void *hook_data) -{ - g_log_set_handler(NULL, G_LOG_LEVEL_DEBUG, g_log_default_handler, NULL); - g_info("Logging set to include DEBUG level messages"); -} - -void lttv_help(void *hook_data) -{ - printf("Linux Trace Toolkit Visualizer\n"); - printf("\n"); - lttv_option_show_help(); - printf("\n"); -} - -/* - -- Make it easier to change modules from builtin to externally loaded. - - have: MODULE_INFO(name, init, destroy, { require} ) in each module. - Maintain the list of builtin modules and search these first (or - optionally last). Add the lib prefix if needed to avoid having to - specify libbatchAnalysis instead of batchAnalysis. - -- Define formally traceset/trace in the GUI for the user and decide how - trace/traceset sharing goes in the application. - -- Use appropriately the new functions in time.h - -- remove the separate tracefiles (control/per cpu) arrays/loops in context. - -- split processTrace into context.c and processTrace.c - -- check spelling conventions. - -- get all the copyright notices. - -- remove all the warnings. - -- get all the .h files properly doxygen commented to produce useful documents. - -- have an intro/architecture document. - -- write a tutorial */ diff --git a/ltt/branches/poly/lttv/main/Makefile.am b/ltt/branches/poly/lttv/main/Makefile.am new file mode 100644 index 00000000..c91d0138 --- /dev/null +++ b/ltt/branches/poly/lttv/main/Makefile.am @@ -0,0 +1,26 @@ +AM_CFLAGS = $(GLIB_CFLAGS) +LIBS += $(GLIB_LIBS) -lgobject-2.0 -L$(top_srcdir)/ltt -ltraceread +#LIBS += $(GLIB_LIBS) -lgobject-2.0 -lltt + +bin_PROGRAMS = lttv + +#AM_CPPFLAGS = \ +# -I$(top_srcdir)/include +#INCLUDES=$(top_srcdir)/include + +lttv_SOURCES = main.c module.c option.c hook.c attribute.c \ + iattribute.c processTrace.c state.c stats.c traceset.c + +libdir = ${lttvplugindir} + +lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la +libtextDump_la_LDFLAGS = -module +libtextDump_la_SOURCES = textDump.c +libbatchAnalysis_la_LDFLAGS = -module +libbatchAnalysis_la_SOURCES = batchAnalysis.c + + +# WARNING : must be done at the end, so modules can dynamically link themselves +# to libraries compiled here but not installed in the system. +SUBDIRS = modules + diff --git a/ltt/branches/poly/lttv/main/main.c b/ltt/branches/poly/lttv/main/main.c new file mode 100644 index 00000000..7b6f7153 --- /dev/null +++ b/ltt/branches/poly/lttv/main/main.c @@ -0,0 +1,221 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +void lttv_option_init(int argc, char **argv); +void lttv_option_destroy(); + +void lttv_module_init(int argc, char **argv); +void lttv_module_destroy(); + +void lttv_state_init(int argc, char **argv); +void lttv_state_destroy(); + +void lttv_stats_init(int argc, char **argv); +void lttv_stats_destroy(); + +/* The main program maintains a few central data structures and relies + on modules for the rest. These data structures may be accessed by modules + through an exported API */ + +static LttvIAttribute *attributes; + +static LttvHooks + *before_options, + *after_options, + *before_main, + *after_main; + +static char + *a_module, + *a_module_path; + +static gboolean + a_verbose, + a_debug; + +static int a_argc; + +static char **a_argv; + +static void lttv_module_option(void *hook_data); + +static void lttv_module_path_option(void *hook_data); + +static void lttv_verbose(void *hook_data); + +static void lttv_debug(void *hook_data); + +static void lttv_help(void *hook_data); + +/* Since everything is done in modules, the main program only takes care + of the infrastructure. */ + +int main(int argc, char **argv) { + + LttvAttributeValue value; + +#ifdef MEMDEBUG + g_mem_set_vtable(glib_mem_profiler_table); + g_message("Memory summary before main"); + g_mem_profile(); +#endif + + g_type_init(); + //g_type_init_with_debug_flags (G_TYPE_DEBUG_OBJECTS | G_TYPE_DEBUG_SIGNALS); + + attributes = LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE, NULL)); + + before_options = lttv_hooks_new(); + after_options = lttv_hooks_new(); + before_main = lttv_hooks_new(); + after_main = lttv_hooks_new(); + + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/options/before", + LTTV_POINTER, &value)); + *(value.v_pointer) = before_options; + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/options/after", + LTTV_POINTER, &value)); + *(value.v_pointer) = after_options; + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/before", + LTTV_POINTER, &value)); + *(value.v_pointer) = before_main; + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/after", + LTTV_POINTER, &value)); + *(value.v_pointer) = after_main; + + + /* Initialize the command line options processing */ + + a_argc = argc; + a_argv = argv; + lttv_option_init(argc,argv); + lttv_module_init(argc,argv); + lttv_state_init(argc,argv); + lttv_stats_init(argc,argv); + + /* Initialize the module loading */ + + lttv_module_path_add("/usr/lib/lttv/plugins"); + + /* Add some built-in options */ + + lttv_option_add("module",'m', "load a module", "name of module to load", + LTTV_OPT_STRING, &a_module, lttv_module_option, NULL); + + lttv_option_add("modules-path", 'L', + "add a directory to the module search path", + "directory to add to the path", LTTV_OPT_STRING, &a_module_path, + lttv_module_path_option, NULL); + + lttv_option_add("help",'h', "basic help", "none", + LTTV_OPT_NONE, NULL, lttv_help, NULL); + + a_verbose = FALSE; + lttv_option_add("verbose",'v', "print information messages", "none", + LTTV_OPT_NONE, NULL, lttv_verbose, NULL); + + a_debug = FALSE; + lttv_option_add("debug",'d', "print debugging messages", "none", + LTTV_OPT_NONE, NULL, lttv_debug, NULL); + + + lttv_hooks_call(before_options, NULL); + lttv_option_parse(argc, argv); + lttv_hooks_call(after_options, NULL); + + lttv_hooks_call(before_main, NULL); + lttv_hooks_call(after_main, NULL); + + lttv_stats_destroy(); + lttv_state_destroy(); + lttv_module_destroy(); + lttv_option_destroy(); + + lttv_hooks_destroy(before_options); + lttv_hooks_destroy(after_options); + lttv_hooks_destroy(before_main); + lttv_hooks_destroy(after_main); + g_object_unref(attributes); + +#ifdef MEMDEBUG + g_message("Memory summary after main"); + g_mem_profile(); +#endif +} + + +LttvAttribute *lttv_global_attributes() +{ + return (LttvAttribute*)attributes; +} + + +void lttv_module_option(void *hook_data) +{ + lttv_module_load(a_module,a_argc,a_argv); +} + + +void lttv_module_path_option(void *hook_data) +{ + lttv_module_path_add(a_module_path); +} + +void lttv_verbose(void *hook_data) +{ + g_log_set_handler(NULL, G_LOG_LEVEL_INFO, g_log_default_handler, NULL); + g_info("Logging set to include INFO level messages"); +} + +void lttv_debug(void *hook_data) +{ + g_log_set_handler(NULL, G_LOG_LEVEL_DEBUG, g_log_default_handler, NULL); + g_info("Logging set to include DEBUG level messages"); +} + +void lttv_help(void *hook_data) +{ + printf("Linux Trace Toolkit Visualizer\n"); + printf("\n"); + lttv_option_show_help(); + printf("\n"); +} + +/* + +- Make it easier to change modules from builtin to externally loaded. + + have: MODULE_INFO(name, init, destroy, { require} ) in each module. + Maintain the list of builtin modules and search these first (or + optionally last). Add the lib prefix if needed to avoid having to + specify libbatchAnalysis instead of batchAnalysis. + +- Define formally traceset/trace in the GUI for the user and decide how + trace/traceset sharing goes in the application. + +- Use appropriately the new functions in time.h + +- remove the separate tracefiles (control/per cpu) arrays/loops in context. + +- split processTrace into context.c and processTrace.c + +- check spelling conventions. + +- get all the copyright notices. + +- remove all the warnings. + +- get all the .h files properly doxygen commented to produce useful documents. + +- have an intro/architecture document. + +- write a tutorial */ diff --git a/ltt/branches/poly/lttv/mainLib/attribute.c b/ltt/branches/poly/lttv/mainLib/attribute.c new file mode 100644 index 00000000..4b6938d7 --- /dev/null +++ b/ltt/branches/poly/lttv/mainLib/attribute.c @@ -0,0 +1,383 @@ + +#include +#include + +typedef union _AttributeValue { + int dv_int; + unsigned dv_uint; + long dv_long; + unsigned long dv_ulong; + float dv_float; + double dv_double; + LttTime dv_time; + gpointer dv_pointer; + char *dv_string; + GObject *dv_gobject; +} AttributeValue; + + +typedef struct _Attribute { + LttvAttributeName name; + LttvAttributeType type; + AttributeValue value; +} Attribute; + + +LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v) +{ + LttvAttributeValue va; + + switch(t) { + case LTTV_INT: va.v_int = &v->dv_int; break; + case LTTV_UINT: va.v_uint = &v->dv_uint; break; + case LTTV_LONG: va.v_long = &v->dv_long; break; + case LTTV_ULONG: va.v_ulong = &v->dv_ulong; break; + case LTTV_FLOAT: va.v_float = &v->dv_float; break; + case LTTV_DOUBLE: va.v_double = &v->dv_double; break; + case LTTV_TIME: va.v_time = &v->dv_time; break; + case LTTV_POINTER: va.v_pointer = &v->dv_pointer; break; + case LTTV_STRING: va.v_string = &v->dv_string; break; + case LTTV_GOBJECT: va.v_gobject = &v->dv_gobject; break; + } + return va; +} + + +AttributeValue init_value(LttvAttributeType t) +{ + AttributeValue v; + + switch(t) { + case LTTV_INT: v.dv_int = 0; break; + case LTTV_UINT: v.dv_uint = 0; break; + case LTTV_LONG: v.dv_long = 0; break; + case LTTV_ULONG: v.dv_ulong = 0; break; + case LTTV_FLOAT: v.dv_float = 0; break; + case LTTV_DOUBLE: v.dv_double = 0; break; + case LTTV_TIME: v.dv_time.tv_sec = 0; v.dv_time.tv_nsec = 0; break; + case LTTV_POINTER: v.dv_pointer = NULL; break; + case LTTV_STRING: v.dv_string = NULL; break; + case LTTV_GOBJECT: v.dv_gobject = NULL; break; + } + return v; +} + + +unsigned int +lttv_attribute_get_number(LttvAttribute *self) +{ + return self->attributes->len; +} + + +gboolean +lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous) +{ + *homogeneous = FALSE; + return TRUE; +} + + +LttvAttributeType +lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name, + LttvAttributeValue *v) +{ + Attribute *a; + + a = &g_array_index(self->attributes, Attribute, i); + *name = a->name; + *v = address_of_value(a->type, &(a->value)); + return a->type; +} + + +LttvAttributeType +lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name, + LttvAttributeValue *v) +{ + Attribute *a; + + unsigned i; + + gpointer p; + + p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(p == NULL) return LTTV_NONE; + + i = GPOINTER_TO_UINT(p); + i--; + a = &g_array_index(self->attributes, Attribute, i); + *v = address_of_value(a->type, &(a->value)); + return a->type; +} + + +LttvAttributeValue +lttv_attribute_add(LttvAttribute *self, LttvAttributeName name, + LttvAttributeType t) +{ + unsigned i; + + Attribute a, *pa; + + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i != 0) g_error("duplicate entry in attribute table"); + + a.name = name; + a.type = t; + a.value = init_value(t); + g_array_append_val(self->attributes, a); + i = self->attributes->len - 1; + pa = &g_array_index(self->attributes, Attribute, i); + g_hash_table_insert(self->names, GUINT_TO_POINTER(name), + GUINT_TO_POINTER(i + 1)); + return address_of_value(t, &(pa->value)); +} + + +/* Remove an attribute */ + +void +lttv_attribute_remove(LttvAttribute *self, unsigned i) +{ + Attribute *a; + + a = &g_array_index(self->attributes, Attribute, i); + + /* Remove the array element and its entry in the name index */ + + g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name)); + g_array_remove_index_fast(self->attributes, i); + + /* The element used to replace the removed element has its index entry + all wrong now. Reinsert it with its new position. */ + + if(self->attributes->len != i){ + g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name)); + g_hash_table_insert(self->names, GUINT_TO_POINTER(a->name), GUINT_TO_POINTER(i + 1)); + } +} + +void +lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name) +{ + unsigned i; + + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i == 0) g_error("remove by name non existent attribute"); + + lttv_attribute_remove(self, i - 1); +} + +/* Create an empty iattribute object and add it as an attribute under the + specified name, or return an existing iattribute attribute. If an + attribute of that name already exists but is not a GObject supporting the + iattribute interface, return NULL. */ + +/*CHECK*/LttvAttribute* +lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name) +{ + unsigned i; + + Attribute a; + + LttvAttribute *new; + + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i != 0) { + a = g_array_index(self->attributes, Attribute, i - 1); + if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) { + return LTTV_ATTRIBUTE(a.value.dv_gobject); + } + else return NULL; + } + new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new); + return (LttvAttribute *)new; +} + +gboolean +lttv_attribute_find(LttvAttribute *self, LttvAttributeName name, + LttvAttributeType t, LttvAttributeValue *v) +{ + unsigned i; + + Attribute *a; + + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i != 0) { + a = &g_array_index(self->attributes, Attribute, i - 1); + if(a->type != t) return FALSE; + *v = address_of_value(t, &(a->value)); + return TRUE; + } + + *v = lttv_attribute_add(self, name, t); + return TRUE; +} + + +void lttv_attribute_recursive_free(LttvAttribute *self) +{ + int i, nb; + + Attribute *a; + + nb = self->attributes->len; + + for(i = 0 ; i < nb ; i++) { + a = &g_array_index(self->attributes, Attribute, i); + if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) { + lttv_attribute_recursive_free((LttvAttribute *)(a->value.dv_gobject)); + } + } + g_object_unref(self); +} + + +void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src) +{ + int i, nb; + + Attribute *a; + + LttvAttributeValue value; + + nb = src->attributes->len; + + for(i = 0 ; i < nb ; i++) { + a = &g_array_index(src->attributes, Attribute, i); + if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) { + lttv_attribute_recursive_add( + /*CHECK*/(LttvAttribute *)lttv_attribute_find_subdir(dest, a->name), + (LttvAttribute *)(a->value.dv_gobject)); + } + else { + g_assert(lttv_attribute_find(dest, a->name, a->type, &value)); + switch(a->type) { + case LTTV_INT: + *value.v_int += a->value.dv_int; + break; + case LTTV_UINT: + *value.v_uint += a->value.dv_uint; + break; + case LTTV_LONG: + *value.v_long += a->value.dv_long; + break; + case LTTV_ULONG: + *value.v_ulong += a->value.dv_ulong; + break; + case LTTV_FLOAT: + *value.v_float += a->value.dv_float; + break; + case LTTV_DOUBLE: + *value.v_double += a->value.dv_double; + break; + case LTTV_TIME: + *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time); + break; + case LTTV_POINTER: + break; + case LTTV_STRING: + break; + case LTTV_GOBJECT: + break; + case LTTV_NONE: + break; + } + } + } +} + + +static void +attribute_interface_init (gpointer g_iface, gpointer iface_data) +{ + LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface; + + klass->get_number = (unsigned int (*) (LttvIAttribute *self)) + lttv_attribute_get_number; + + klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous)) + lttv_attribute_named; + + klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i, + LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get; + + klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self, + LttvAttributeName name, LttvAttributeValue *v)) + lttv_attribute_get_by_name; + + klass->add = (LttvAttributeValue (*) (LttvIAttribute *self, + LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add; + + klass->remove = (void (*) (LttvIAttribute *self, unsigned i)) + lttv_attribute_remove; + + klass->remove_by_name = (void (*) (LttvIAttribute *self, + LttvAttributeName name)) lttv_attribute_remove_by_name; + + klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self, + LttvAttributeName name)) lttv_attribute_find_subdir; +} + + +static void +attribute_instance_init (GTypeInstance *instance, gpointer g_class) +{ + LttvAttribute *self = (LttvAttribute *)instance; + self->names = g_hash_table_new(g_direct_hash, g_direct_equal); + self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute)); +} + + +static void +attribute_finalize (LttvAttribute *self) +{ + g_hash_table_destroy(self->names); + g_critical("attribute_finalize()"); + g_array_free(self->attributes, TRUE); + G_OBJECT_CLASS(g_type_class_peek_parent( + g_type_class_peek(LTTV_ATTRIBUTE_TYPE)))->finalize(G_OBJECT(self)); +} + + +static void +attribute_class_init (LttvAttributeClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self))attribute_finalize; +} + +GType +lttv_attribute_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvAttributeClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) attribute_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvAttribute), + 0, /* n_preallocs */ + (GInstanceInitFunc) attribute_instance_init /* instance_init */ + }; + + static const GInterfaceInfo iattribute_info = { + (GInterfaceInitFunc) attribute_interface_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info, + 0); + g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info); + } + return type; +} + + diff --git a/ltt/branches/poly/lttv/mainLib/filter.c b/ltt/branches/poly/lttv/mainLib/filter.c new file mode 100644 index 00000000..c63940ba --- /dev/null +++ b/ltt/branches/poly/lttv/mainLib/filter.c @@ -0,0 +1,58 @@ + + consist in AND, OR and NOT nested expressions, forming a tree with + simple relations as leaves. The simple relations test is a field + in an event is equal, not equal, smaller, smaller or equal, larger, or + larger or equal to a specified value. */ + +typedef enum _lttv_expression_op +{ LTTV_FIELD_EQ, + LTTV_FIELD_NE, + LTTV_FIELD_LT, + LTTV_FIELD_LE, + LTTV_FIELD_GT, + LTTV_FIELD_GE +} lttv_expression_op; + +typedef _lttv_simple_expression +{ lttv_expression_op op; + char *field_name; + char *value; +} lttv_simple_expression; + +typedef _lttv_expression_type +{ LTTV_EXPRESSION, + LTTV_SIMPLE_EXPRESSION + +} +typedef struct _lttv_expression +{ bool or; + bool not; + bool simple_expression; + union + { lttv_expression *e; + lttv_field_relation *se; + } e; +} lttv_expression; + +read_token + +read_expression + ( read expr ) + simple expr [ op expr ] + +read_simple_expression + read_field_path [ rel value ] + +read_field_path + read_field_component [. field path] + +read_field_component + name [ \[ value \] ] + +data struct: +and/or(left/right) +not(child) +op(left/right) +path(component...) -> field + + diff --git a/ltt/branches/poly/lttv/mainLib/hook.c b/ltt/branches/poly/lttv/mainLib/hook.c new file mode 100644 index 00000000..8edbb2af --- /dev/null +++ b/ltt/branches/poly/lttv/mainLib/hook.c @@ -0,0 +1,212 @@ + +#include + + +typedef struct _LttvHookClosure { + LttvHook hook; + void *hook_data; +} LttvHookClosure; + + +LttvHooks *lttv_hooks_new() +{ + return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure)); +} + + +void lttv_hooks_destroy(LttvHooks *h) +{ + g_critical("lttv_hooks_destroy()"); + g_array_free(h, TRUE); +} + + +void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data) +{ + LttvHookClosure c; + + if(h == NULL)g_error("Null hook added"); + + c.hook = f; + c.hook_data = hook_data; + g_array_append_val(h,c); +} + + +void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list) +{ + guint i; + + if(list == NULL) return; + for(i = 0 ; i < list->len; i++) { + g_array_append_val(h,g_array_index(list, LttvHookClosure, i)); + } +} + + +void *lttv_hooks_remove(LttvHooks *h, LttvHook f) +{ + unsigned i; + + void *hook_data; + + LttvHookClosure *c; + + for(i = 0 ; i < h->len ; i++) { + c = &g_array_index(h, LttvHookClosure, i); + if(c->hook == f) { + hook_data = c->hook_data; + lttv_hooks_remove_by_position(h, i); + return hook_data; + } + } + return NULL; +} + + +void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data) +{ + unsigned i; + + LttvHookClosure *c; + + for(i = 0 ; i < h->len ; i++) { + c = &g_array_index(h, LttvHookClosure, i); + if(c->hook == f && c->hook_data == hook_data) { + lttv_hooks_remove_by_position(h, i); + return; + } + } +} + + +void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list) +{ + guint i, j; + + LttvHookClosure *c, *c_list; + + if(list == NULL) return; + for(i = 0, j = 0 ; i < h->len && j < list->len ;) { + c = &g_array_index(h, LttvHookClosure, i); + c_list = &g_array_index(list, LttvHookClosure, j); + if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) { + lttv_hooks_remove_by_position(h, i); + j++; + } + else i++; + } + + /* Normally the hooks in h are ordered as in list. If this is not the case, + try harder here. */ + + if(j < list->len) { + for(; j < list->len ; j++) { + c_list = &g_array_index(list, LttvHookClosure, j); + lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data); + } + } +} + + +unsigned lttv_hooks_number(LttvHooks *h) +{ + return h->len; +} + + +void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data) +{ + LttvHookClosure *c; + + c = &g_array_index(h, LttvHookClosure, i); + *f = c->hook; + *hook_data = c->hook_data; +} + + +void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i) +{ + g_array_remove_index(h, i); +} + + +gboolean lttv_hooks_call(LttvHooks *h, void *call_data) +{ + gboolean ret, sum_ret = FALSE; + + LttvHookClosure *c; + + guint i; + + if(h != NULL) { + for(i = 0 ; i < h->len ; i++) { + c = &g_array_index(h, LttvHookClosure, i); + ret = c->hook(c->hook_data,call_data); + sum_ret = sum_ret || ret; + } + } + return sum_ret; +} + + +gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data) +{ + LttvHookClosure *c; + + guint i; + + for(i = 0 ; i < h->len ; i++) { + c = &g_array_index(h, LttvHookClosure, i); + if(c->hook(c->hook_data,call_data)) return TRUE; + } + return FALSE; +} + + +LttvHooksById *lttv_hooks_by_id_new() +{ + return g_ptr_array_new(); +} + + +void lttv_hooks_by_id_destroy(LttvHooksById *h) +{ + guint i; + + for(i = 0 ; i < h->len ; i++) { + if(h->pdata[i] != NULL) lttv_hooks_destroy((LttvHooks *)(h->pdata[i])); + } + g_ptr_array_free(h, TRUE); +} + + +LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id) +{ + if(h->len <= id) g_ptr_array_set_size(h, id + 1); + if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new(); + return h->pdata[id]; +} + + +unsigned lttv_hooks_by_id_max_id(LttvHooksById *h) +{ + return h->len; +} + + +LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id) +{ + if(id < h->len) return h->pdata[id]; + return NULL; +} + + +void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id) +{ + if(id < h->len && h->pdata[id] != NULL) { + lttv_hooks_destroy((LttvHooks *)h->pdata[id]); + h->pdata[id] = NULL; + } +} + diff --git a/ltt/branches/poly/lttv/mainLib/iattribute.c b/ltt/branches/poly/lttv/mainLib/iattribute.c new file mode 100644 index 00000000..e39d7e08 --- /dev/null +++ b/ltt/branches/poly/lttv/mainLib/iattribute.c @@ -0,0 +1,260 @@ + +#include + +static void +lttv_iattribute_base_init (gpointer klass) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + initialized = TRUE; + } +} + + +GType +lttv_iattribute_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvIAttributeClass), + lttv_iattribute_base_init, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL /* instance_init */ + }; + type = g_type_register_static (G_TYPE_INTERFACE, "LttvIAttribute", + &info, 0); + } + return type; +} + + +unsigned int lttv_iattribute_get_number(LttvIAttribute *self) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->get_number (self); +} + + +gboolean lttv_iattribute_named(LttvIAttribute *self, gboolean *homogeneous) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->named (self, homogeneous); +} + + +LttvAttributeType lttv_iattribute_get(LttvIAttribute *self, unsigned i, + LttvAttributeName *name, LttvAttributeValue *v) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->get (self, i, name, v); +} + + +LttvAttributeType lttv_iattribute_get_by_name(LttvIAttribute *self, + LttvAttributeName name, LttvAttributeValue *v) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->get_by_name (self, name, v); +} + + +LttvAttributeValue lttv_iattribute_add(LttvIAttribute *self, + LttvAttributeName name, LttvAttributeType t) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->add (self, name, t); +} + + +void lttv_iattribute_remove(LttvIAttribute *self, unsigned i) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->remove (self, i); +} + + +void lttv_iattribute_remove_by_name(LttvIAttribute *self, + LttvAttributeName name) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->remove_by_name (self, name); +} + +LttvIAttribute* lttv_iattribute_find_subdir(LttvIAttribute *self, + LttvAttributeName name) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->find_subdir (self, name); +} + + +/* Find the named attribute in the table, which must be of the specified type. + If it does not exist, it is created with a default value of 0 (NULL for + pointer types). Since the address of the value is obtained, it may be + changed easily afterwards. The function returns false when the attribute + exists but is of incorrect type. */ + +gboolean lttv_iattribute_find(LttvIAttribute *self, LttvAttributeName name, + LttvAttributeType t, LttvAttributeValue *v) +{ + LttvAttributeType found_type; + + found_type = lttv_iattribute_get_by_name(self, name, v); + if(found_type == t) return TRUE; + + if(found_type == LTTV_NONE) { + *v = lttv_iattribute_add(self, name, t); + return TRUE; + } + + return FALSE; +} + + +/* Trees of attribute tables may be accessed using a hierarchical path with + components separated by /, like in filesystems */ + +gboolean lttv_iattribute_find_by_path(LttvIAttribute *self, char *path, + LttvAttributeType t, LttvAttributeValue *v) +{ + LttvIAttribute *node = self; + + LttvAttributeType found_type; + + LttvAttributeName name; + + gchar **components, **cursor; + + components = g_strsplit(path, "\"", G_MAXINT); + + if(components == NULL || *components == NULL) { + g_strfreev(components); + return FALSE; + } + + for(cursor = components;;) { + name = g_quark_from_string(*cursor); + cursor++; + + if(*cursor == NULL) { + g_strfreev(components); + return lttv_iattribute_find(node, name, t, v); + } + else { + found_type = lttv_iattribute_get_by_name(node, name, v); + if(found_type == LTTV_NONE) { + node = lttv_iattribute_find_subdir(node, name); + } + else if(found_type == LTTV_GOBJECT && + LTTV_IS_IATTRIBUTE(*(v->v_gobject))) { + node = LTTV_IATTRIBUTE(*(v->v_gobject)); + } + else { + g_strfreev(components); + return FALSE; + } + } + } +} + +/* Shallow and deep copies */ + +LttvIAttribute *lttv_iattribute_shallow_copy(LttvIAttribute *self) +{ + LttvIAttribute *copy; + + LttvAttributeType t; + + LttvAttributeValue v, v_copy; + + LttvAttributeName name; + + int i; + + int nb_attributes = lttv_iattribute_get_number(self); + + copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self),NULL)); + + for(i = 0 ; i < nb_attributes ; i++) { + t = lttv_iattribute_get(self, i, &name, &v); + v_copy = lttv_iattribute_add(copy, name, t); + lttv_iattribute_copy_value(t, v_copy, v); + } +} + +LttvIAttribute *lttv_iattribute_deep_copy(LttvIAttribute *self) +{ + LttvIAttribute *copy, *child; + + LttvAttributeType t; + + LttvAttributeValue v, v_copy; + + LttvAttributeName name; + + int i; + + int nb_attributes = lttv_iattribute_get_number(self); + + copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self), NULL)); + + for(i = 0 ; i < nb_attributes ; i++) { + t = lttv_iattribute_get(self, i, &name, &v); + v_copy = lttv_iattribute_add(copy, name, t); + if(t == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(*(v.v_gobject))) { + child = LTTV_IATTRIBUTE(*(v.v_gobject)); + *(v_copy.v_gobject) = G_OBJECT(lttv_iattribute_deep_copy(child)); + } + else lttv_iattribute_copy_value(t, v_copy, v); + } +} + +void lttv_iattribute_copy_value(LttvAttributeType t, LttvAttributeValue dest, + LttvAttributeValue src) +{ + switch(t) { + case LTTV_INT: + *(dest.v_int) = *(src.v_int); + break; + + case LTTV_UINT: + *(dest.v_uint) = *(src.v_uint); + break; + + case LTTV_LONG: + *(dest.v_long) = *(src.v_long); + break; + + case LTTV_ULONG: + *(dest.v_ulong) = *(src.v_ulong); + break; + + case LTTV_FLOAT: + *(dest.v_float) = *(src.v_float); + break; + + case LTTV_DOUBLE: + *(dest.v_double) = *(src.v_double); + break; + + case LTTV_TIME: + *(dest.v_time) = *(src.v_time); + break; + + case LTTV_POINTER: + *(dest.v_pointer) = *(src.v_pointer); + break; + + case LTTV_STRING: + *(dest.v_string) = *(src.v_string); + break; + + case LTTV_GOBJECT: + *(dest.v_gobject) = *(src.v_gobject); + break; + + case LTTV_NONE: + break; + } +} + + diff --git a/ltt/branches/poly/lttv/mainLib/module.c b/ltt/branches/poly/lttv/mainLib/module.c new file mode 100644 index 00000000..e225992a --- /dev/null +++ b/ltt/branches/poly/lttv/mainLib/module.c @@ -0,0 +1,302 @@ + +/* module.c : Implementation of the module loading/unloading mechanism. + * + */ + +#include + +#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) +#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) + +struct _LttvModule +{ + GModule *module; + guint ref_count; + guint load_count; + GPtrArray *dependents; +}; + + +/* Table of loaded modules and paths where to search for modules */ + +static GHashTable *modules = NULL; + +static GPtrArray *modulesPaths = NULL; + +static void lttv_module_unload_all(); + + +void lttv_module_init(int argc, char **argv) +{ + g_info("Init module.c"); + modules = g_hash_table_new(g_str_hash, g_str_equal); + modulesPaths = g_ptr_array_new(); +} + + +void lttv_module_destroy() +{ + int i; + + g_info("Destroy module.c"); + + /* Unload all modules */ + lttv_module_unload_all(); + + /* Free the modules paths pointer array as well as the elements */ + for(i = 0; i < modulesPaths->len ; i++) { + g_free(modulesPaths->pdata[i]); + } + g_ptr_array_free(modulesPaths,TRUE) ; + modulesPaths = NULL; + + /* destroy the hash table */ + g_hash_table_destroy(modules) ; + modules = NULL; +} + + +/* Add a new pathname to the modules loading search path */ + +void lttv_module_path_add(const char *name) +{ + g_info("Add module path %s", name); + g_ptr_array_add(modulesPaths,(char*)g_strdup(name)); +} + + +static LttvModule * +module_load(const char *name, int argc, char **argv) +{ + GModule *gm; + + LttvModule *m; + + int i; + + char *pathname; + + const char *module_name; + + LttvModuleInit init_function; + + g_info("Load module %s", name); + + /* Try to find the module along all the user specified paths */ + + for(i = 0 ; i < modulesPaths->len ; i++) { + pathname = g_module_build_path(modulesPaths->pdata[i],name); + g_info("Try path %s", pathname); + gm = g_module_open(pathname,0); + g_free(pathname); + + if(gm != NULL) break; + g_info("Trial failed, %s", g_module_error()); + } + + /* Try the default system path */ + + if(gm == NULL) { + pathname = g_module_build_path(NULL,name); + g_info("Try default path"); + gm = g_module_open(pathname,0); + g_free(pathname); + } + + /* Module cannot be found */ + if(gm == NULL) { + g_info("Trial failed, %s", g_module_error()); + g_info("Failed to load %s", name); + return NULL; + } + + /* Check if the module was already opened using the hopefully canonical name + returned by g_module_name. */ + + module_name = g_module_name(gm); + + m = g_hash_table_lookup(modules, module_name); + + if(m == NULL) { + g_info("Module %s (%s) loaded, call its init function", name, module_name); + + /* Module loaded for the first time. Insert it in the table and call the + init function if any. */ + + m = g_new(LttvModule, 1); + m->module = gm; + m->ref_count = 0; + m->load_count = 0; + m->dependents = g_ptr_array_new(); + g_hash_table_insert(modules, (gpointer)module_name, m); + + if(!g_module_symbol(gm, "init", (gpointer)&init_function)) { + g_warning("module %s (%s) has no init function", name, pathname); + } + else init_function(m, argc, argv); + } + else { + + /* Module was already opened, check that it really is the same and + undo the extra g_module_open */ + + g_info("Module %s (%s) was already loaded, no need to call init function", + name, module_name); + if(m->module != gm) g_error("Two gmodules with the same pathname"); + g_module_close(gm); + } + + m->ref_count++; + return m; +} + + +LttvModule * +lttv_module_load(const char *name, int argc, char **argv) +{ + g_info("Load module %s explicitly", name); + LttvModule *m = module_load(name, argc, argv); + if(m != NULL) m->load_count++; + return m; +} + + +LttvModule * +lttv_module_require(LttvModule *m, const char *name, int argc, char **argv) +{ + LttvModule *module; + + g_info("Load module %s, as %s is a dependent requiring it", name, + g_module_name(m->module)); + module = module_load(name, argc, argv); + if(module != NULL) g_ptr_array_add(module->dependents, m); + return module; +} + + +static void module_unload(LttvModule *m) +{ + LttvModuleDestroy destroy_function; + + char *pathname; + + guint i, len; + + /* Decrement the reference count */ + + g_info("Unload module %s", g_module_name(m->module)); + m->ref_count--; + if(m->ref_count > 0) { + g_info("Module usage count decremented to %d", m->ref_count); + return; + } + /* We really have to unload the module, first unload its dependents */ + + len = m->dependents->len; + g_info("Unload dependent modules"); + + for(i = 0 ; i < len ; i++) { + module_unload(m->dependents->pdata[i]); + } + + if(len != m->dependents->len) g_error("dependents list modified"); + + /* Unload the module itself */ + + g_info("Call the destroy function and unload the module"); + if(!g_module_symbol(m->module, "destroy", (gpointer)&destroy_function)) { + g_warning("module (%s) has no destroy function", pathname); + } + else destroy_function(); + + g_hash_table_remove(modules, g_module_name(m->module)); + g_ptr_array_free(m->dependents, TRUE); + g_module_close(m->module); + g_free(m); +} + + +void lttv_module_unload(LttvModule *m) +{ + g_info("Explicitly unload module %s", g_module_name(m->module)); + if(m->load_count <= 0) { + g_error("more unload than load (%s)", g_module_name(m->module)); + return; + } + m->load_count--; + module_unload(m); +} + + +static void +list_modules(gpointer key, gpointer value, gpointer user_data) +{ + g_ptr_array_add((GPtrArray *)user_data, value); +} + + +LttvModule ** +lttv_module_list(guint *nb) +{ + GPtrArray *list = g_ptr_array_new(); + + LttvModule **array; + + g_hash_table_foreach(modules, list_modules, list); + *nb = list->len; + array = (LttvModule **)list->pdata; + g_ptr_array_free(list, FALSE); + return array; +} + + +LttvModule ** +lttv_module_info(LttvModule *m, const char **name, + guint *ref_count, guint *load_count, guint *nb_dependents) +{ + guint i, len = m->dependents->len; + + LttvModule **array = g_new(LttvModule *, len); + + *name = g_module_name(m->module); + *ref_count = m->ref_count; + *load_count = m->load_count; + *nb_dependents = len; + for(i = 0 ; i < len ; i++) array[i] = m->dependents->pdata[i]; + return array; +} + +char * +lttv_module_name(LttvModule *m) +{ + return g_module_name(m->module); +} + +static void +list_independent(gpointer key, gpointer value, gpointer user_data) +{ + LttvModule *m = (LttvModule *)value; + + if(m->load_count > 0) g_ptr_array_add((GPtrArray *)user_data, m); +} + + +void +lttv_module_unload_all() +{ + guint i; + + LttvModule *m; + + GPtrArray *independent_modules = g_ptr_array_new(); + + g_hash_table_foreach(modules, list_independent, independent_modules); + + for(i = 0 ; i < independent_modules->len ; i++) { + m = (LttvModule *)independent_modules->pdata[i]; + while(m->load_count > 0) lttv_module_unload(m); + } + + g_ptr_array_free(independent_modules, TRUE); + if(g_hash_table_size(modules) != 0) g_warning("cannot unload all modules"); +} diff --git a/ltt/branches/poly/lttv/mainLib/option.c b/ltt/branches/poly/lttv/mainLib/option.c new file mode 100644 index 00000000..590f9def --- /dev/null +++ b/ltt/branches/poly/lttv/mainLib/option.c @@ -0,0 +1,264 @@ + +#include +#include +#include + +#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) +#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) + +typedef struct _LttvOption { + char *long_name; + char char_name; + char *description; + char *arg_description; + LttvOptionType t; + gpointer p; + LttvOptionHook hook; + gpointer hook_data; +} LttvOption; + +GHashTable *options; + + +static void +list_options(gpointer key, gpointer value, gpointer user_data) +{ + g_ptr_array_add((GPtrArray *)user_data, value); +} + + +static void +free_option(LttvOption *option) +{ + g_free(option->long_name); + g_free(option->description); + g_free(option->arg_description); + g_free(option); +} + + +void lttv_option_init(int argc, char **argv) +{ + g_info("Init option.c"); + options = g_hash_table_new(g_str_hash, g_str_equal); +} + + +void lttv_option_destroy() +{ + LttvOption option; + + GPtrArray *list = g_ptr_array_new(); + + int i; + + g_info("Destroy option.c"); + g_hash_table_foreach(options, list_options, list); + g_hash_table_destroy(options); + + for(i = 0 ; i < list->len ; i++) { + free_option((LttvOption *)list->pdata[i]); + } + g_ptr_array_free(list, TRUE); +} + + +void lttv_option_add(const char *long_name, const char char_name, + const char *description, const char *arg_description, + const LttvOptionType t, void *p, + const LttvOptionHook h, void *hook_data) +{ + LttvOption *option; + + g_info("Add option %s", long_name); + if(g_hash_table_lookup(options, long_name) != NULL) { + g_warning("duplicate option"); + return; + } + + option = g_new(LttvOption, 1); + option->long_name = g_strdup(long_name); + option->char_name = char_name; + option->description = g_strdup(description); + option->arg_description = g_strdup(arg_description); + option->t = t; + option->p = p; + option->hook = h; + option->hook_data = hook_data; + g_hash_table_insert(options, option->long_name, option); +} + + +void +lttv_option_remove(const char *long_name) +{ + LttvOption *option = g_hash_table_lookup(options, long_name); + + g_info("Remove option %s", long_name); + if(option == NULL) { + g_warning("trying to remove unknown option %s", long_name); + return; + } + g_hash_table_remove(options, long_name); + free_option(option); +} + + +static int poptToLTT[] = { + POPT_ARG_NONE, POPT_ARG_STRING, POPT_ARG_INT, POPT_ARG_LONG +}; + +static struct poptOption endOption = { NULL, '\0', 0, NULL, 0}; + + +static void +build_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc, + int argc, char **argv) +{ + LttvOption *option; + + GPtrArray *list; + + struct poptOption *popts; + + poptContext c; + + guint i; + + list = g_ptr_array_new(); + + g_hash_table_foreach(options, list_options, list); + + /* Build a popt options array from our list */ + + popts = g_new(struct poptOption, list->len + 1); + + for(i = 0 ; i < list->len ; i++) { + option = (LttvOption *)list->pdata[i]; + popts[i].longName = option->long_name; + popts[i].shortName = option->char_name; + popts[i].descrip = option->description; + popts[i].argDescrip = option->arg_description; + popts[i].argInfo = poptToLTT[option->t]; + popts[i].arg = option->p; + popts[i].val = i + 1; + } + + /* Terminate the array for popt and create the context */ + + popts[list->len] = endOption; + c = poptGetContext(argv[0], argc, (const char**)argv, popts, 0); + + *plist = list; + *ppopts = popts; + *pc = c; +} + + +static void +destroy_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc) +{ + g_ptr_array_free(*plist, TRUE); *plist = NULL; + g_free(*ppopts); *ppopts = NULL; + poptFreeContext(*pc); +} + + +void lttv_option_parse(int argc, char **argv) +{ + GPtrArray *list; + + LttvOption *option; + + int i, rc, first_arg; + + struct poptOption *popts; + + poptContext c; + + i = 0; + + first_arg = 0; + + build_popts(&list, &popts, &c, argc, argv); + + /* Parse options while not end of options event */ + + while((rc = poptGetNextOpt(c)) != -1) { + + /* The option was recognized and the rc value returned is the argument + position in the array. Call the associated hook if present. */ + + if(rc > 0) { + option = (LttvOption *)(list->pdata[rc - 1]); + g_info("Option %s encountered", option->long_name); + if(option->hook != NULL) { + g_info("Option %s hook called", option->long_name); + option->hook(option->hook_data); + } + i++; + } + + else if(rc == POPT_ERROR_BADOPT && i != first_arg) { + g_info("Option %s not recognized, rescan options with new additions", + poptBadOption(c,0)); + + /* Perhaps this option is newly added, restart parsing */ + + destroy_popts(&list, &popts, &c); + build_popts(&list, &popts, &c, argc, argv); + + /* Get back to the same argument */ + + first_arg = i; + for(i = 0; i < first_arg; i++) { + rc = poptGetNextOpt(c); + option = (LttvOption *)(list->pdata[rc - 1]); + g_info("Option %s rescanned, skipped", option->long_name); + } + } + + else { + + /* The option has some error and it is not because this is a newly + added option not recognized. */ + + g_error("option %s: %s", poptBadOption(c,0), poptStrerror(rc)); + break; + } + + } + + destroy_popts(&list, &popts, &c); +} + +static void show_help(LttvOption *option) +{ + printf("--%s -%c argument: %s\n" , option->long_name, + option->char_name, + option->arg_description); + printf(" %s\n" , option->description); + +} + +void lttv_option_show_help(void) +{ + LttvOption option; + + GPtrArray *list = g_ptr_array_new(); + + int i; + + g_hash_table_foreach(options, list_options, list); + + printf("Built-in commands available:\n"); + printf("\n"); + + for(i = 0 ; i < list->len ; i++) { + show_help((LttvOption *)list->pdata[i]); + } + g_ptr_array_free(list, TRUE); + + +} + diff --git a/ltt/branches/poly/lttv/mainLib/processTrace.c b/ltt/branches/poly/lttv/mainLib/processTrace.c new file mode 100644 index 00000000..4a290dd0 --- /dev/null +++ b/ltt/branches/poly/lttv/mainLib/processTrace.c @@ -0,0 +1,812 @@ + +#include +#include +#include +#include +#include + +void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts) +{ + LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts); +} + + +void lttv_context_fini(LttvTracesetContext *self) +{ + LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self); +} + + +LttvTracesetContext * +lttv_context_new_traceset_context(LttvTracesetContext *self) +{ + return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self); +} + + + + +LttvTraceContext * +lttv_context_new_trace_context(LttvTracesetContext *self) +{ + return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self); +} + + +LttvTracefileContext * +lttv_context_new_tracefile_context(LttvTracesetContext *self) +{ + return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self); +} + +/**************************************************************************** + * lttv_traceset_context_compute_time_span + * + * Keep the Time_Span is sync with on the fly addition and removal of traces + * in a trace set. It must be called each time a trace is added/removed from + * the traceset. It could be more efficient to call it only once a bunch + * of traces are loaded, but the calculation is not long, so it's not + * critical. + * + * Author : Xang Xiu Yang + * Imported from gtkTraceSet.c by Mathieu Desnoyers + ***************************************************************************/ +static void lttv_traceset_context_compute_time_span( + LttvTracesetContext *self, + TimeInterval *Time_Span) +{ + LttvTraceset * traceset = self->ts; + int numTraces = lttv_traceset_number(traceset); + int i; + LttTime s, e; + LttvTraceContext *tc; + LttTrace * trace; + + for(i=0; itraces[i]; + trace = tc->t; + + ltt_trace_time_span_get(trace, &s, &e); + + if(i==0){ + Time_Span->startTime = s; + Time_Span->endTime = e; + }else{ + if(s.tv_sec < Time_Span->startTime.tv_sec || + (s.tv_sec == Time_Span->startTime.tv_sec + && s.tv_nsec < Time_Span->startTime.tv_nsec)) + Time_Span->startTime = s; + if(e.tv_sec > Time_Span->endTime.tv_sec || + (e.tv_sec == Time_Span->endTime.tv_sec && + e.tv_nsec > Time_Span->endTime.tv_nsec)) + Time_Span->endTime = e; + } + } +} + + +static void +init(LttvTracesetContext *self, LttvTraceset *ts) +{ + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTracefileContext *tfc; + + LttTime null_time = {0, 0}; + + nb_trace = lttv_traceset_number(ts); + self->ts = ts; + self->traces = g_new(LttvTraceContext *, nb_trace); + self->before = lttv_hooks_new(); + self->after = lttv_hooks_new(); + self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + self->ts_a = lttv_traceset_attribute(ts); + for(i = 0 ; i < nb_trace ; i++) { + tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self); + self->traces[i] = tc; + + tc->ts_context = self; + tc->index = i; + tc->vt = lttv_traceset_get(ts, i); + tc->t = lttv_trace(tc->vt); + tc->check = lttv_hooks_new(); + tc->before = lttv_hooks_new(); + tc->after = lttv_hooks_new(); + tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + tc->t_a = lttv_trace_attribute(tc->vt); + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + tc->control_tracefiles = g_new(LttvTracefileContext *, nb_control); + tc->per_cpu_tracefiles = g_new(LttvTracefileContext *, nb_per_cpu); + + for(j = 0 ; j < nb_tracefile ; j++) { + tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self); + if(j < nb_control) { + tc->control_tracefiles[j] = tfc; + tfc->control = TRUE; + tfc->index = j; + tfc->tf = ltt_trace_control_tracefile_get(tc->t, j); + } + else { + tc->per_cpu_tracefiles[j - nb_control] = tfc; + tfc->control = FALSE; + tfc->index = j - nb_control; + tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control); + } + tfc->t_context = tc; + tfc->check = lttv_hooks_new(); + tfc->before = lttv_hooks_new(); + tfc->after = lttv_hooks_new(); + tfc->check_event = lttv_hooks_new(); + tfc->before_event = lttv_hooks_new(); + tfc->before_event_by_id = lttv_hooks_by_id_new(); + tfc->after_event = lttv_hooks_new(); + tfc->after_event_by_id = lttv_hooks_by_id_new(); + tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + } + } + lttv_process_traceset_seek_time(self, null_time); + /*CHECK why dynamically allocate the time span... and the casing is wroNg*/ + self->Time_Span = g_new(TimeInterval,1); + lttv_traceset_context_compute_time_span(self, self->Time_Span); +} + + +void fini(LttvTracesetContext *self) +{ + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTracefileContext *tfc; + + LttvTraceset *ts = self->ts; + + g_free(self->Time_Span); + + lttv_hooks_destroy(self->before); + lttv_hooks_destroy(self->after); + //FIXME : segfault + g_object_unref(self->a); + + nb_trace = lttv_traceset_number(ts); + + for(i = 0 ; i < nb_trace ; i++) { + tc = self->traces[i]; + + lttv_hooks_destroy(tc->check); + lttv_hooks_destroy(tc->before); + lttv_hooks_destroy(tc->after); + g_object_unref(tc->a); + + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) tfc = tc->control_tracefiles[j]; + else tfc = tc->per_cpu_tracefiles[j - nb_control]; + + lttv_hooks_destroy(tfc->check); + lttv_hooks_destroy(tfc->before); + lttv_hooks_destroy(tfc->after); + lttv_hooks_destroy(tfc->check_event); + lttv_hooks_destroy(tfc->before_event); + lttv_hooks_by_id_destroy(tfc->before_event_by_id); + lttv_hooks_destroy(tfc->after_event); + lttv_hooks_by_id_destroy(tfc->after_event_by_id); + g_object_unref(tfc->a); + g_object_unref(tfc); + } + g_free(tc->control_tracefiles); + g_free(tc->per_cpu_tracefiles); + g_object_unref(tc); + } + g_free(self->traces); +} + + +void lttv_traceset_context_add_hooks(LttvTracesetContext *self, + LttvHooks *before_traceset, + LttvHooks *after_traceset, + LttvHooks *check_trace, + LttvHooks *before_trace, + LttvHooks *after_trace, + LttvHooks *check_tracefile, + LttvHooks *before_tracefile, + LttvHooks *after_tracefile, + LttvHooks *check_event, + LttvHooks *before_event, + LttvHooks *after_event) +{ + LttvTraceset *ts = self->ts; + + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTracefileContext *tfc; + + void *hook_data; + + lttv_hooks_add_list(self->before, before_traceset); + lttv_hooks_add_list(self->after, after_traceset); + nb_trace = lttv_traceset_number(ts); + + for(i = 0 ; i < nb_trace ; i++) { + tc = self->traces[i]; + lttv_hooks_add_list(tc->check, check_trace); + lttv_hooks_add_list(tc->before, before_trace); + lttv_hooks_add_list(tc->after, after_trace); + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfc = tc->control_tracefiles[j]; + } + else { + tfc = tc->per_cpu_tracefiles[j-nb_control]; + } + lttv_hooks_add_list(tfc->check, check_tracefile); + lttv_hooks_add_list(tfc->before, before_tracefile); + lttv_hooks_add_list(tfc->after, after_tracefile); + lttv_hooks_add_list(tfc->check_event, check_event); + lttv_hooks_add_list(tfc->before_event, before_event); + lttv_hooks_add_list(tfc->after_event, after_event); + } + } +} + + +void lttv_traceset_context_remove_hooks(LttvTracesetContext *self, + LttvHooks *before_traceset, + LttvHooks *after_traceset, + LttvHooks *check_trace, + LttvHooks *before_trace, + LttvHooks *after_trace, + LttvHooks *check_tracefile, + LttvHooks *before_tracefile, + LttvHooks *after_tracefile, + LttvHooks *check_event, + LttvHooks *before_event, + LttvHooks *after_event) +{ + LttvTraceset *ts = self->ts; + + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTracefileContext *tfc; + + void *hook_data; + + lttv_hooks_remove_list(self->before, before_traceset); + lttv_hooks_remove_list(self->after, after_traceset); + nb_trace = lttv_traceset_number(ts); + + for(i = 0 ; i < nb_trace ; i++) { + tc = self->traces[i]; + lttv_hooks_remove_list(tc->check, check_trace); + lttv_hooks_remove_list(tc->before, before_trace); + lttv_hooks_remove_list(tc->after, after_trace); + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfc = tc->control_tracefiles[j]; + } + else { + tfc = tc->per_cpu_tracefiles[j-nb_control]; + } + lttv_hooks_remove_list(tfc->check, check_tracefile); + lttv_hooks_remove_list(tfc->before, before_tracefile); + lttv_hooks_remove_list(tfc->after, after_tracefile); + lttv_hooks_remove_list(tfc->check_event, check_event); + lttv_hooks_remove_list(tfc->before_event, before_event); + lttv_hooks_remove_list(tfc->after_event, after_event); + } + } +} + +void lttv_trace_context_add_hooks(LttvTraceContext *tc, + LttvHooks *check_trace, + LttvHooks *before_trace, + LttvHooks *after_trace) +{ + lttv_hooks_add_list(tc->check, check_trace); + lttv_hooks_add_list(tc->before, before_trace); + lttv_hooks_add_list(tc->after, after_trace); +} + +void lttv_trace_context_remove_hooks(LttvTraceContext *tc, + LttvHooks *check_trace, + LttvHooks *before_trace, + LttvHooks *after_trace) +{ + lttv_hooks_remove_list(tc->check, check_trace); + lttv_hooks_remove_list(tc->before, before_trace); + lttv_hooks_remove_list(tc->after, after_trace); +} + +void lttv_tracefile_context_add_hooks(LttvTracefileContext *tfc, + LttvHooks *check_tracefile, + LttvHooks *before_tracefile, + LttvHooks *after_tracefile, + LttvHooks *check_event, + LttvHooks *before_event, + LttvHooks *after_event) +{ + lttv_hooks_add_list(tfc->check, check_tracefile); + lttv_hooks_add_list(tfc->before, before_tracefile); + lttv_hooks_add_list(tfc->after, after_tracefile); + lttv_hooks_add_list(tfc->check_event, check_event); + lttv_hooks_add_list(tfc->before_event, before_event); + lttv_hooks_add_list(tfc->after_event, after_event); +} + +void lttv_tracefile_context_remove_hooks(LttvTracefileContext *tfc, + LttvHooks *check_tracefile, + LttvHooks *before_tracefile, + LttvHooks *after_tracefile, + LttvHooks *check_event, + LttvHooks *before_event, + LttvHooks *after_event) +{ + lttv_hooks_remove_list(tfc->check, check_tracefile); + lttv_hooks_remove_list(tfc->before, before_tracefile); + lttv_hooks_remove_list(tfc->after, after_tracefile); + lttv_hooks_remove_list(tfc->check_event, check_event); + lttv_hooks_remove_list(tfc->before_event, before_event); + lttv_hooks_remove_list(tfc->after_event, after_event); +} + +void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc, + unsigned i, + LttvHooks *before_event_by_id, + LttvHooks *after_event_by_id) +{ + LttvHooks * h; + h = lttv_hooks_by_id_find(tfc->before_event_by_id, i); + lttv_hooks_add_list(h, before_event_by_id); + h = lttv_hooks_by_id_find(tfc->after_event_by_id, i); + lttv_hooks_add_list(h, after_event_by_id); +} + +void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc, + unsigned i) +{ + lttv_hooks_by_id_remove(tfc->before_event_by_id, i); + lttv_hooks_by_id_remove(tfc->after_event_by_id, i); +} + +static LttvTracesetContext * +new_traceset_context(LttvTracesetContext *self) +{ + return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL); +} + + +static LttvTraceContext * +new_trace_context(LttvTracesetContext *self) +{ + return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL); +} + + +static LttvTracefileContext * +new_tracefile_context(LttvTracesetContext *self) +{ + return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL); +} + + +static void +traceset_context_instance_init (GTypeInstance *instance, gpointer g_class) +{ + /* Be careful of anything which would not work well with shallow copies */ +} + + +static void +traceset_context_finalize (LttvTracesetContext *self) +{ + G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE))) + ->finalize(G_OBJECT(self)); +} + + +static void +traceset_context_class_init (LttvTracesetContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize; + klass->init = init; + klass->fini = fini; + klass->new_traceset_context = new_traceset_context; + klass->new_trace_context = new_trace_context; + klass->new_tracefile_context = new_tracefile_context; +} + + +GType +lttv_traceset_context_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracesetContextClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) traceset_context_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracesetContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) traceset_context_instance_init /* instance_init */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType", + &info, 0); + } + return type; +} + + +static void +trace_context_instance_init (GTypeInstance *instance, gpointer g_class) +{ + /* Be careful of anything which would not work well with shallow copies */ +} + + +static void +trace_context_finalize (LttvTraceContext *self) +{ + G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))-> + finalize(G_OBJECT(self)); +} + + +static void +trace_context_class_init (LttvTraceContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize; +} + + +GType +lttv_trace_context_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTraceContextClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) trace_context_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTraceContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) trace_context_instance_init /* instance_init */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType", + &info, 0); + } + return type; +} + + +static void +tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class) +{ + /* Be careful of anything which would not work well with shallow copies */ +} + + +static void +tracefile_context_finalize (LttvTracefileContext *self) +{ + G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE))) + ->finalize(G_OBJECT(self)); +} + + +static void +tracefile_context_class_init (LttvTracefileContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize; +} + + +GType +lttv_tracefile_context_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracefileContextClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) tracefile_context_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracefileContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) tracefile_context_instance_init /* instance_init */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType", + &info, 0); + } + return type; +} + + +gint compare_tracefile(gconstpointer a, gconstpointer b) +{ + return ltt_time_compare(*((LttTime *)a), *((LttTime *)b)); +} + + +gboolean get_first(gpointer key, gpointer value, gpointer user_data) { + *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value; + return TRUE; +} + + +void lttv_process_traceset(LttvTracesetContext *self, LttTime end, + unsigned maxNumEvents) +{ + GPtrArray *traces = g_ptr_array_new(); + + GPtrArray *tracefiles = g_ptr_array_new(); + + GTree *pqueue = g_tree_new(compare_tracefile); + + guint i, j, nbi, nbj, id, nb_control, nb_cpu; + + LttTrace *trace; + + LttvTraceContext *tc; + + LttTracefile *tracefile; + + LttvTracefileContext *tfc; + + LttEvent *event; + + unsigned count = 0; + + LttTime previous_timestamp = {0, 0}; + + /* Call all before_traceset, before_trace, and before_tracefile hooks. + For all qualifying tracefiles, seek to the start time, create a context, + read one event and insert in the pqueue based on the event time. */ + + lttv_hooks_call(self->before, self); + nbi = lttv_traceset_number(self->ts); + + for(i = 0 ; i < nbi ; i++) { + tc = self->traces[i]; + trace = tc->t; + + if(!lttv_hooks_call_check(tc->check, tc)) { + g_ptr_array_add(traces, tc); + lttv_hooks_call(tc->before, tc); + nb_control = ltt_trace_control_tracefile_number(trace); + nb_cpu = ltt_trace_per_cpu_tracefile_number(trace); + nbj = nb_control + nb_cpu; + + for(j = 0 ; j < nbj ; j++) { + if(j < nb_control) { + tfc = tc->control_tracefiles[j]; + } + else { + tfc = tc->per_cpu_tracefiles[j - nb_control]; + } + + tracefile = tfc->tf; + + if(!lttv_hooks_call_check(tfc->check, tfc)) { + g_ptr_array_add(tracefiles, tfc); + lttv_hooks_call(tfc->before, tfc); + + if(tfc->e != NULL) { + if(tfc->timestamp.tv_sec < end.tv_sec || + (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec)){ + g_tree_insert(pqueue, &(tfc->timestamp), tfc); + } + } + } + } + } + } + + /* Get the next event from the pqueue, call its hooks, + reinsert in the pqueue the following event from the same tracefile + unless the tracefile is finished or the event is later than the + start time. */ + + while(TRUE) { + tfc = NULL; + g_tree_foreach(pqueue, get_first, &tfc); + if(tfc == NULL) break; + + /* Have we reached the maximum number of events specified? However, + continue for all the events with the same time stamp (CHECK?). Then, + empty the queue and break from the loop. */ + + count++; + if(count > maxNumEvents){ + if(tfc->timestamp.tv_sec == previous_timestamp.tv_sec && + tfc->timestamp.tv_nsec == previous_timestamp.tv_nsec) { + count--; + }else{ + while(TRUE){ + tfc = NULL; + g_tree_foreach(pqueue, get_first, &tfc); + if(tfc == NULL) break; + g_tree_remove(pqueue, &(tfc->timestamp)); + } + break; + } + } + previous_timestamp = tfc->timestamp; + + + /* Get the tracefile with an event for the smallest time found. If two + or more tracefiles have events for the same time, hope that lookup + and remove are consistent. */ + + tfc = g_tree_lookup(pqueue, &(tfc->timestamp)); + g_tree_remove(pqueue, &(tfc->timestamp)); + + if(!lttv_hooks_call(tfc->check_event, tfc)) { + id = ltt_event_eventtype_id(tfc->e); + lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc); + lttv_hooks_call(tfc->before_event, tfc); + lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc); + lttv_hooks_call(tfc->after_event, tfc); + } + + event = ltt_tracefile_read(tfc->tf); + if(event != NULL) { + tfc->e = event; + tfc->timestamp = ltt_event_time(event); + if(tfc->timestamp.tv_sec < end.tv_sec || + (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec)) + g_tree_insert(pqueue, &(tfc->timestamp), tfc); + } + } + + /* Call all the after_tracefile, after_trace and after_traceset hooks. */ + + for(i = 0, j = 0 ; i < traces->len ; i++) { + tc = traces->pdata[i]; + while(j < tracefiles->len) { + tfc = tracefiles->pdata[j]; + + if(tfc->t_context == tc) { + lttv_hooks_call(tfc->after, tfc); + j++; + } + else break; + } + lttv_hooks_call(tc->after, tc); + } + + g_assert(j == tracefiles->len); + lttv_hooks_call(self->after, self); + + /* Free the traces, tracefiles and pqueue */ + + g_ptr_array_free(tracefiles, TRUE); + g_ptr_array_free(traces, TRUE); + g_tree_destroy(pqueue); +} + + +void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileContext *tfc; + + LttEvent *event; + + nb_control = ltt_trace_control_tracefile_number(self->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->t); + nb_tracefile = nb_control + nb_per_cpu; + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) tfc = self->control_tracefiles[i]; + else tfc = self->per_cpu_tracefiles[i - nb_control]; + + ltt_tracefile_seek_time(tfc->tf, start); + event = ltt_tracefile_read(tfc->tf); + tfc->e = event; + if(event != NULL) tfc->timestamp = ltt_event_time(event); + } +} + + +void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start) +{ + guint i, nb_trace; + + LttvTraceContext *tc; + + nb_trace = lttv_traceset_number(self->ts); + for(i = 0 ; i < nb_trace ; i++) { + tc = self->traces[i]; + lttv_process_trace_seek_time(tc, start); + } +} + + +static LttField * +find_field(LttEventType *et, const char *field) +{ + LttType *t; + + LttField *f; + + guint i, nb; + + char *name; + + if(field == NULL) return NULL; + + f = ltt_eventtype_field(et); + t = ltt_eventtype_type(et); + g_assert(ltt_type_class(t) == LTT_STRUCT); + nb = ltt_type_member_number(t); + for(i = 0 ; i < nb ; i++) { + ltt_type_member_type(t, i, &name); + if(strcmp(name, field) == 0) break; + } + g_assert(i < nb); + return ltt_field_member(f, i); +} + + +void +lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type, + char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th) +{ + LttFacility *f; + + LttEventType *et; + + guint nb, pos, i; + + char *name; + + nb = ltt_trace_facility_find(t, facility, &pos); + if(nb < 1) g_error("No %s facility", facility); + f = ltt_trace_facility_get(t, pos); + et = ltt_facility_eventtype_get_by_name(f, event_type); + if(et == NULL) g_error("Event %s does not exist", event_type); + + th->h = h; + th->id = ltt_eventtype_id(et); + th->f1 = find_field(et, field1); + th->f2 = find_field(et, field2); + th->f3 = find_field(et, field3); +} + + diff --git a/ltt/branches/poly/lttv/mainLib/state.c b/ltt/branches/poly/lttv/mainLib/state.c new file mode 100644 index 00000000..dbdb11ce --- /dev/null +++ b/ltt/branches/poly/lttv/mainLib/state.c @@ -0,0 +1,1198 @@ + +#include +#include +#include +#include +#include + +LttvExecutionMode + LTTV_STATE_MODE_UNKNOWN, + LTTV_STATE_USER_MODE, + LTTV_STATE_SYSCALL, + LTTV_STATE_TRAP, + LTTV_STATE_IRQ; + +LttvExecutionSubmode + LTTV_STATE_SUBMODE_UNKNOWN, + LTTV_STATE_SUBMODE_NONE; + +LttvProcessStatus + LTTV_STATE_UNNAMED, + LTTV_STATE_WAIT_FORK, + LTTV_STATE_WAIT_CPU, + LTTV_STATE_EXIT, + LTTV_STATE_WAIT, + LTTV_STATE_RUN; + +static GQuark + LTTV_STATE_TRACEFILES, + LTTV_STATE_PROCESSES, + LTTV_STATE_PROCESS, + LTTV_STATE_EVENT, + LTTV_STATE_SAVED_STATES, + LTTV_STATE_TIME, + LTTV_STATE_HOOKS; + + +static void fill_name_tables(LttvTraceState *tcs); + +static void free_name_tables(LttvTraceState *tcs); + +static void lttv_state_free_process_table(GHashTable *processes); + +static LttvProcessState *create_process(LttvTracefileState *tfs, + LttvProcessState *parent, guint pid); + +void lttv_state_save(LttvTraceState *self, LttvAttribute *container) +{ + LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container); +} + + +void lttv_state_restore(LttvTraceState *self, LttvAttribute *container) +{ + LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); +} + + +void lttv_state_saved_state_free(LttvTraceState *self, + LttvAttribute *container) +{ + LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); +} + + +static void +restore_init_state(LttvTraceState *self) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileState *tfcs; + + LttTime null_time = {0,0}; + + if(self->processes != NULL) lttv_state_free_process_table(self->processes); + self->processes = g_hash_table_new(g_direct_hash, g_direct_equal); + self->nb_event = 0; + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) { + tfcs = LTTV_TRACEFILE_STATE(self->parent.control_tracefiles[i]); + } + else { + tfcs = LTTV_TRACEFILE_STATE(self->parent.per_cpu_tracefiles[i - nb_control]); + } + + tfcs->parent.timestamp = null_time; + tfcs->saved_position = 0; + tfcs->process = create_process(tfcs, NULL,0); + } +} + + +static void +init(LttvTracesetState *self, LttvTraceset *ts) +{ + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTraceState *tcs; + + LttvTracefileState *tfcs; + + LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> + init((LttvTracesetContext *)self, ts); + + nb_trace = lttv_traceset_number(ts); + for(i = 0 ; i < nb_trace ; i++) { + tc = self->parent.traces[i]; + tcs = (LttvTraceState *)tc; + tcs->save_interval = 100000; + fill_name_tables(tcs); + + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfcs = LTTV_TRACEFILE_STATE(tc->control_tracefiles[j]); + } + else { + tfcs = LTTV_TRACEFILE_STATE(tc->per_cpu_tracefiles[j - nb_control]); + } + tfcs->cpu_name= g_quark_from_string(ltt_tracefile_name(tfcs->parent.tf)); + } + tcs->processes = NULL; + restore_init_state(tcs); + } +} + + +static void +fini(LttvTracesetState *self) +{ + guint i, j, nb_trace, nb_tracefile; + + LttvTraceState *tcs; + + LttvTracefileState *tfcs; + + nb_trace = lttv_traceset_number(LTTV_TRACESET_CONTEXT(self)->ts); + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceState *)(LTTV_TRACESET_CONTEXT(self)->traces[i]); + lttv_state_free_process_table(tcs->processes); + tcs->processes = NULL; + free_name_tables(tcs); + } + LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> + fini((LttvTracesetContext *)self); +} + + +static LttvTracesetContext * +new_traceset_context(LttvTracesetContext *self) +{ + return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE, NULL)); +} + + +static LttvTraceContext * +new_trace_context(LttvTracesetContext *self) +{ + return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE, NULL)); +} + + +static LttvTracefileContext * +new_tracefile_context(LttvTracesetContext *self) +{ + return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE, NULL)); +} + + +static void copy_process_state(gpointer key, gpointer value,gpointer user_data) +{ + LttvProcessState *process, *new_process; + + GHashTable *new_processes = (GHashTable *)user_data; + + guint i; + + process = (LttvProcessState *)value; + new_process = g_new(LttvProcessState, 1); + *new_process = *process; + new_process->execution_stack = g_array_new(FALSE, FALSE, + sizeof(LttvExecutionState)); + g_array_set_size(new_process->execution_stack,process->execution_stack->len); + for(i = 0 ; i < process->execution_stack->len; i++) { + g_array_index(new_process->execution_stack, LttvExecutionState, i) = + g_array_index(process->execution_stack, LttvExecutionState, i); + } + new_process->state = &g_array_index(new_process->execution_stack, + LttvExecutionState, new_process->execution_stack->len - 1); + g_hash_table_insert(new_processes, GUINT_TO_POINTER(new_process->pid), + new_process); +} + + +static GHashTable *lttv_state_copy_process_table(GHashTable *processes) +{ + GHashTable *new_processes = g_hash_table_new(g_direct_hash, g_direct_equal); + + g_hash_table_foreach(processes, copy_process_state, new_processes); + return new_processes; +} + + +/* The saved state for each trace contains a member "processes", which + stores a copy of the process table, and a member "tracefiles" with + one entry per tracefile. Each tracefile has a "process" member pointing + to the current process and a "position" member storing the tracefile + position (needed to seek to the current "next" event. */ + +static void state_save(LttvTraceState *self, LttvAttribute *container) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileState *tfcs; + + LttvAttribute *tracefiles_tree, *tracefile_tree; + + LttvAttributeType type; + + LttvAttributeValue value; + + LttvAttributeName name; + + LttEventPosition *ep; + + tracefiles_tree = lttv_attribute_find_subdir(container, + LTTV_STATE_TRACEFILES); + + value = lttv_attribute_add(container, LTTV_STATE_PROCESSES, + LTTV_POINTER); + *(value.v_pointer) = lttv_state_copy_process_table(self->processes); + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) + tfcs = (LttvTracefileState *)self->parent.control_tracefiles[i]; + else tfcs = (LttvTracefileState *) + self->parent.per_cpu_tracefiles[i - nb_control]; + + tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + value = lttv_attribute_add(tracefiles_tree, i, + LTTV_GOBJECT); + *(value.v_gobject) = (GObject *)tracefile_tree; + value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS, + LTTV_UINT); + *(value.v_uint) = tfcs->process->pid; + value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT, + LTTV_POINTER); + if(tfcs->parent.e == NULL) *(value.v_pointer) = NULL; + else { + ep = ltt_event_position_new(); + ltt_event_position(tfcs->parent.e, ep); + *(value.v_pointer) = ep; + } + } +} + + +static void state_restore(LttvTraceState *self, LttvAttribute *container) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileState *tfcs; + + LttvAttribute *tracefiles_tree, *tracefile_tree; + + LttvAttributeType type; + + LttvAttributeValue value; + + LttvAttributeName name; + + LttEventPosition *ep; + + tracefiles_tree = lttv_attribute_find_subdir(container, + LTTV_STATE_TRACEFILES); + + type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, + &value); + g_assert(type == LTTV_POINTER); + lttv_state_free_process_table(self->processes); + self->processes = lttv_state_copy_process_table(*(value.v_pointer)); + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) tfcs = (LttvTracefileState *) + self->parent.control_tracefiles[i]; + else tfcs = (LttvTracefileState *) + self->parent.per_cpu_tracefiles[i - nb_control]; + + type = lttv_attribute_get(tracefiles_tree, i, &name, &value); + g_assert(type == LTTV_GOBJECT); + tracefile_tree = *((LttvAttribute **)(value.v_gobject)); + + type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_PROCESS, + &value); + g_assert(type == LTTV_UINT); + tfcs->process = lttv_state_find_process(tfcs, *(value.v_uint)); + type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, + &value); + g_assert(type == LTTV_POINTER); + if(*(value.v_pointer) == NULL) tfcs->parent.e = NULL; + else { + ep = *(value.v_pointer); + ltt_tracefile_seek_position(tfcs->parent.tf, ep); + tfcs->parent.e = ltt_tracefile_read(tfcs->parent.tf); + tfcs->parent.timestamp = ltt_event_time(tfcs->parent.e); + } + } +} + + +static void state_saved_free(LttvTraceState *self, LttvAttribute *container) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileState *tfcs; + + LttvAttribute *tracefiles_tree, *tracefile_tree; + + LttvAttributeType type; + + LttvAttributeValue value; + + LttvAttributeName name; + + LttEventPosition *ep; + + tracefiles_tree = lttv_attribute_find_subdir(container, + LTTV_STATE_TRACEFILES); + lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES); + + type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, + &value); + g_assert(type == LTTV_POINTER); + lttv_state_free_process_table(*(value.v_pointer)); + *(value.v_pointer) = NULL; + lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES); + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) tfcs = (LttvTracefileState *) + self->parent.control_tracefiles[i]; + else tfcs = (LttvTracefileState *) + self->parent.per_cpu_tracefiles[i - nb_control]; + + type = lttv_attribute_get(tracefiles_tree, i, &name, &value); + g_assert(type == LTTV_GOBJECT); + tracefile_tree = *((LttvAttribute **)(value.v_gobject)); + + type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, + &value); + g_assert(type == LTTV_POINTER); + if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer)); + } + lttv_attribute_recursive_free(tracefiles_tree); +} + + +static void +fill_name_tables(LttvTraceState *tcs) +{ + int i, nb; + + char *f_name, *e_name; + + LttvTraceHook h; + + LttEventType *et; + + LttType *t; + + GString *fe_name = g_string_new(""); + + nb = ltt_trace_eventtype_number(tcs->parent.t); + tcs->eventtype_names = g_new(GQuark, nb); + for(i = 0 ; i < nb ; i++) { + et = ltt_trace_eventtype_get(tcs->parent.t, i); + e_name = ltt_eventtype_name(et); + f_name = ltt_facility_name(ltt_eventtype_facility(et)); + g_string_printf(fe_name, "%s.%s", f_name, e_name); + tcs->eventtype_names[i] = g_quark_from_string(fe_name->str); + } + + lttv_trace_find_hook(tcs->parent.t, "core", "syscall_entry", + "syscall_id", NULL, NULL, NULL, &h); + t = ltt_field_type(h.f1); + nb = ltt_type_element_number(t); + + /* CHECK syscalls should be an emun but currently are not! + tcs->syscall_names = g_new(GQuark, nb); + + for(i = 0 ; i < nb ; i++) { + tcs->syscall_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + } + */ + + tcs->syscall_names = g_new(GQuark, 256); + for(i = 0 ; i < 256 ; i++) { + g_string_printf(fe_name, "syscall %d", i); + tcs->syscall_names[i] = g_quark_from_string(fe_name->str); + } + + lttv_trace_find_hook(tcs->parent.t, "core", "trap_entry", + "trap_id", NULL, NULL, NULL, &h); + t = ltt_field_type(h.f1); + nb = ltt_type_element_number(t); + + /* + tcs->trap_names = g_new(GQuark, nb); + for(i = 0 ; i < nb ; i++) { + tcs->trap_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + } + */ + + tcs->trap_names = g_new(GQuark, 256); + for(i = 0 ; i < 256 ; i++) { + g_string_printf(fe_name, "trap %d", i); + tcs->trap_names[i] = g_quark_from_string(fe_name->str); + } + + lttv_trace_find_hook(tcs->parent.t, "core", "irq_entry", + "irq_id", NULL, NULL, NULL, &h); + t = ltt_field_type(h.f1); + nb = ltt_type_element_number(t); + + /* + tcs->irq_names = g_new(GQuark, nb); + for(i = 0 ; i < nb ; i++) { + tcs->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + } + */ + + tcs->irq_names = g_new(GQuark, 256); + for(i = 0 ; i < 256 ; i++) { + g_string_printf(fe_name, "irq %d", i); + tcs->irq_names[i] = g_quark_from_string(fe_name->str); + } + + g_string_free(fe_name, TRUE); +} + + +static void +free_name_tables(LttvTraceState *tcs) +{ + g_free(tcs->eventtype_names); + g_free(tcs->syscall_names); + g_free(tcs->trap_names); + g_free(tcs->irq_names); +} + + +static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, + guint state_id) +{ + LttvExecutionState *es; + + LttvProcessState *process = tfs->process; + + guint depth = process->execution_stack->len; + + g_array_set_size(process->execution_stack, depth + 1); + es = &g_array_index(process->execution_stack, LttvExecutionState, depth); + es->t = t; + es->n = state_id; + es->entry = es->change = tfs->parent.timestamp; + es->s = process->state->s; + process->state = es; +} + + +static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) +{ + LttvProcessState *process = tfs->process; + + guint depth = process->execution_stack->len - 1; + + if(process->state->t != t){ + g_warning("Different execution mode type (%d.%09d): ignore it\n", + tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + g_warning("process state has %s when pop_int is %s\n", + g_quark_to_string(process->state->t), + g_quark_to_string(t)); + g_warning("{ %u, %u, %s, %s }\n", + process->pid, + process->ppid, + g_quark_to_string(process->name), + g_quark_to_string(process->state->s)); + return; + } + + if(depth == 0){ + g_warning("Trying to pop last state on stack (%d.%09d): ignore it\n", + tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + return; + } + + g_array_remove_index(process->execution_stack, depth); + depth--; + process->state = &g_array_index(process->execution_stack, LttvExecutionState, + depth); + process->state->change = tfs->parent.timestamp; +} + + +static LttvProcessState *create_process(LttvTracefileState *tfs, + LttvProcessState *parent, guint pid) +{ + LttvProcessState *process = g_new(LttvProcessState, 1); + + LttvExecutionState *es; + + LttvTraceContext *tc; + + LttvTraceState *tcs; + + char buffer[128]; + + tcs = (LttvTraceState *)tc = tfs->parent.t_context; + + g_hash_table_insert(tcs->processes, GUINT_TO_POINTER(pid), process); + process->pid = pid; + + if(parent) { + process->ppid = parent->pid; + process->name = parent->name; + } + else { + process->ppid = 0; + process->name = LTTV_STATE_UNNAMED; + } + + process->creation_time = tfs->parent.timestamp; + sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec, + process->creation_time.tv_nsec); + process->pid_time = g_quark_from_string(buffer); + process->execution_stack = g_array_new(FALSE, FALSE, + sizeof(LttvExecutionState)); + g_array_set_size(process->execution_stack, 1); + es = process->state = &g_array_index(process->execution_stack, + LttvExecutionState, 0); + es->t = LTTV_STATE_USER_MODE; + es->n = LTTV_STATE_SUBMODE_NONE; + es->entry = tfs->parent.timestamp; + es->change = tfs->parent.timestamp; + es->s = LTTV_STATE_WAIT_FORK; + + return process; +} + + +LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs, + guint pid) +{ + LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context; + LttvProcessState *process = g_hash_table_lookup(ts->processes, + GUINT_TO_POINTER(pid)); + if(process == NULL) process = create_process(tfs, NULL, pid); + return process; +} + + +static void exit_process(LttvTracefileState *tfs, LttvProcessState *process) +{ + LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context); + + g_hash_table_remove(ts->processes, GUINT_TO_POINTER(process->pid)); + g_array_free(process->execution_stack, TRUE); + g_free(process); +} + + +static void free_process_state(gpointer key, gpointer value,gpointer user_data) +{ + g_array_free(((LttvProcessState *)value)->execution_stack, TRUE); + g_free(value); +} + + +static void lttv_state_free_process_table(GHashTable *processes) +{ + g_hash_table_foreach(processes, free_process_state, NULL); + g_hash_table_destroy(processes); +} + + +static gboolean syscall_entry(void *hook_data, void *call_data) +{ + LttField *f = ((LttvTraceHook *)hook_data)->f1; + + LttvTracefileState *s = (LttvTracefileState *)call_data; + + LttvExecutionSubmode submode; + + submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[ + ltt_event_get_unsigned(s->parent.e, f)]; + push_state(s, LTTV_STATE_SYSCALL, submode); + return FALSE; +} + + +static gboolean syscall_exit(void *hook_data, void *call_data) +{ + LttvTracefileState *s = (LttvTracefileState *)call_data; + + pop_state(s, LTTV_STATE_SYSCALL); + return FALSE; +} + + +static gboolean trap_entry(void *hook_data, void *call_data) +{ + LttField *f = ((LttvTraceHook *)hook_data)->f1; + + LttvTracefileState *s = (LttvTracefileState *)call_data; + + LttvExecutionSubmode submode; + + submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[ + ltt_event_get_unsigned(s->parent.e, f)]; + push_state(s, LTTV_STATE_TRAP, submode); + return FALSE; +} + + +static gboolean trap_exit(void *hook_data, void *call_data) +{ + LttvTracefileState *s = (LttvTracefileState *)call_data; + + pop_state(s, LTTV_STATE_TRAP); + return FALSE; +} + + +static gboolean irq_entry(void *hook_data, void *call_data) +{ + LttField *f = ((LttvTraceHook *)hook_data)->f1; + + LttvTracefileState *s = (LttvTracefileState *)call_data; + + LttvExecutionSubmode submode; + + submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[ + ltt_event_get_unsigned(s->parent.e, f)]; + + /* Do something with the info about being in user or system mode when int? */ + push_state(s, LTTV_STATE_IRQ, submode); + return FALSE; +} + + +static gboolean irq_exit(void *hook_data, void *call_data) +{ + LttvTracefileState *s = (LttvTracefileState *)call_data; + + pop_state(s, LTTV_STATE_IRQ); + return FALSE; +} + + +static gboolean schedchange(void *hook_data, void *call_data) +{ + LttvTraceHook *h = (LttvTraceHook *)hook_data; + + LttvTracefileState *s = (LttvTracefileState *)call_data; + + guint pid_in, pid_out, state_out; + + pid_in = ltt_event_get_unsigned(s->parent.e, h->f1); + pid_out = ltt_event_get_unsigned(s->parent.e, h->f2); + state_out = ltt_event_get_unsigned(s->parent.e, h->f3); + + if(s->process != NULL) { + + if(state_out == 0) s->process->state->s = LTTV_STATE_WAIT_CPU; + else if(s->process->state->s == LTTV_STATE_EXIT) + exit_process(s, s->process); + else s->process->state->s = LTTV_STATE_WAIT; + + if(s->process->pid == 0) + s->process->pid = pid_out; + + s->process->state->change = s->parent.timestamp; + } + s->process = lttv_state_find_process(s, pid_in); + s->process->state->s = LTTV_STATE_RUN; + s->process->state->change = s->parent.timestamp; + return FALSE; +} + + +static gboolean process_fork(void *hook_data, void *call_data) +{ + LttField *f = ((LttvTraceHook *)hook_data)->f1; + + LttvTracefileState *s = (LttvTracefileState *)call_data; + + guint child_pid; + + child_pid = ltt_event_get_unsigned(s->parent.e, f); + create_process(s, s->process, child_pid); + return FALSE; +} + + +static gboolean process_exit(void *hook_data, void *call_data) +{ + LttvTracefileState *s = (LttvTracefileState *)call_data; + + if(s->process != NULL) { + s->process->state->s = LTTV_STATE_EXIT; + } + return FALSE; +} + + +void lttv_state_add_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + GArray *hooks; + + LttvTraceHook hook; + + LttvAttributeValue val; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = (LttvTraceState *)self->parent.traces[i]; + + /* Find the eventtype id for the following events and register the + associated by id hooks. */ + + hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); + g_array_set_size(hooks, 9); + + lttv_trace_find_hook(ts->parent.t, "core","syscall_entry","syscall_id", + NULL, NULL, syscall_entry, &g_array_index(hooks, LttvTraceHook, 0)); + + lttv_trace_find_hook(ts->parent.t, "core", "syscall_exit", NULL, NULL, + NULL, syscall_exit, &g_array_index(hooks, LttvTraceHook, 1)); + + lttv_trace_find_hook(ts->parent.t, "core", "trap_entry", "trap_id", + NULL, NULL, trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); + + lttv_trace_find_hook(ts->parent.t, "core", "trap_exit", NULL, NULL, NULL, + trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); + + lttv_trace_find_hook(ts->parent.t, "core", "irq_entry", "irq_id", NULL, + NULL, irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); + + lttv_trace_find_hook(ts->parent.t, "core", "irq_exit", NULL, NULL, NULL, + irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); + + lttv_trace_find_hook(ts->parent.t, "core", "schedchange", "in", "out", + "out_state", schedchange, &g_array_index(hooks, LttvTraceHook, 6)); + + lttv_trace_find_hook(ts->parent.t, "core", "process_fork", "child_pid", + NULL, NULL, process_fork, &g_array_index(hooks, LttvTraceHook, 7)); + + lttv_trace_find_hook(ts->parent.t, "core", "process_exit", NULL, NULL, + NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 8)); + + /* Add these hooks to each before_event_by_id hooks list */ + + nb_control = ltt_trace_control_tracefile_number(ts->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); + } + else { + tfs = LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); + } + + for(k = 0 ; k < hooks->len ; k++) { + hook = g_array_index(hooks, LttvTraceHook, k); + lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, + hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k)); + } + } + lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val); + *(val.v_pointer) = hooks; + } +} + + +void lttv_state_remove_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + GArray *hooks; + + LttvTraceHook hook; + + LttvAttributeValue val; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = LTTV_TRACE_STATE(self->parent.traces[i]); + lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val); + hooks = *(val.v_pointer); + + /* Add these hooks to each before_event_by_id hooks list */ + + nb_control = ltt_trace_control_tracefile_number(ts->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); + } + else { + tfs = LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); + } + + for(k = 0 ; k < hooks->len ; k++) { + hook = g_array_index(hooks, LttvTraceHook, k); + lttv_hooks_remove_data( + lttv_hooks_by_id_find(tfs->parent.after_event_by_id, + hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k)); + } + } + g_array_free(hooks, TRUE); + } +} + + +static gboolean block_end(void *hook_data, void *call_data) +{ + LttvTracefileState *tfcs = (LttvTracefileState *)call_data; + + LttvTraceState *tcs = (LttvTraceState *)(tfcs->parent.t_context); + + LttEventPosition *ep = ltt_event_position_new(); + + guint nb_block, nb_event; + + LttTracefile *tf; + + LttvAttribute *saved_states_tree, *saved_state_tree; + + LttvAttributeValue value; + + ltt_event_position(tfcs->parent.e, ep); + + ltt_event_position_get(ep, &nb_block, &nb_event, &tf); + tcs->nb_event += nb_event - tfcs->saved_position; + tfcs->saved_position = 0; + if(tcs->nb_event >= tcs->save_interval) { + saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, + LTTV_STATE_SAVED_STATES); + saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + value = lttv_attribute_add(saved_states_tree, + lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT); + *(value.v_gobject) = (GObject *)saved_state_tree; + value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME); + *(value.v_time) = tfcs->parent.timestamp; + lttv_state_save(tcs, saved_state_tree); + tcs->nb_event = 0; + } + return FALSE; +} + + +void lttv_state_save_add_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + LttvTraceHook hook; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = (LttvTraceState *)self->parent.traces[i]; + lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, + NULL, NULL, block_end, &hook); + + nb_control = ltt_trace_control_tracefile_number(ts->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); + } + else { + tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); + } + + lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, + hook.id), hook.h, NULL); + } + } +} + + +void lttv_state_save_remove_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + LttvTraceHook hook; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = LTTV_TRACE_STATE(self->parent.traces[i]); + lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, + NULL, NULL, block_end, &hook); + + nb_control = ltt_trace_control_tracefile_number(ts->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); + } + else { + tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); + } + + lttv_hooks_remove_data(lttv_hooks_by_id_find( + tfs->parent.after_event_by_id, hook.id), hook.h, NULL); + } + } +} + + +void lttv_state_restore_closest_state(LttvTracesetState *self, LttTime t) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, nb_trace, nb_saved_state; + + int min_pos, mid_pos, max_pos; + + LttvTraceState *tcs; + + LttvAttributeValue value; + + LttvAttributeType type; + + LttvAttributeName name; + + LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceState *)self->parent.traces[i]; + + saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, + LTTV_STATE_SAVED_STATES); + min_pos = -1; + max_pos = lttv_attribute_get_number(saved_states_tree) - 1; + mid_pos = max_pos / 2; + while(min_pos < max_pos) { + type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value); + g_assert(type == LTTV_GOBJECT); + saved_state_tree = *((LttvAttribute **)(value.v_gobject)); + type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME, + &value); + g_assert(type == LTTV_TIME); + if(ltt_time_compare(*(value.v_time), t) < 0) { + min_pos = mid_pos; + closest_tree = saved_state_tree; + } + else max_pos = mid_pos - 1; + + mid_pos = (min_pos + max_pos + 1) / 2; + } + if(min_pos == -1) { + restore_init_state(tcs); + lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero); + } + else lttv_state_restore(tcs, closest_tree); + } +} + + +static void +traceset_state_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +traceset_state_finalize (LttvTracesetState *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +traceset_state_class_init (LttvTracesetContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize; + klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init; + klass->fini = (void (*)(LttvTracesetContext *self))fini; + klass->new_traceset_context = new_traceset_context; + klass->new_trace_context = new_trace_context; + klass->new_tracefile_context = new_tracefile_context; +} + + +GType +lttv_traceset_state_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracesetStateClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) traceset_state_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracesetContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) traceset_state_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType", + &info, 0); + } + return type; +} + + +static void +trace_state_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +trace_state_finalize (LttvTraceState *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +trace_state_class_init (LttvTraceStateClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize; + klass->state_save = state_save; + klass->state_restore = state_restore; + klass->state_saved_free = state_saved_free; +} + + +GType +lttv_trace_state_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTraceStateClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) trace_state_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTraceState), + 0, /* n_preallocs */ + (GInstanceInitFunc) trace_state_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE, + "LttvTraceStateType", &info, 0); + } + return type; +} + + +static void +tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +tracefile_state_finalize (LttvTracefileState *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +tracefile_state_class_init (LttvTracefileStateClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize; +} + + +GType +lttv_tracefile_state_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracefileStateClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) tracefile_state_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracefileState), + 0, /* n_preallocs */ + (GInstanceInitFunc) tracefile_state_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE, + "LttvTracefileStateType", &info, 0); + } + return type; +} + + +void lttv_state_init(int argc, char **argv) +{ + LTTV_STATE_UNNAMED = g_quark_from_string("unnamed"); + LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode"); + LTTV_STATE_USER_MODE = g_quark_from_string("user mode"); + LTTV_STATE_WAIT_FORK = g_quark_from_string("wait fork"); + LTTV_STATE_SYSCALL = g_quark_from_string("system call"); + LTTV_STATE_TRAP = g_quark_from_string("trap"); + LTTV_STATE_IRQ = g_quark_from_string("irq"); + LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("unknown submode"); + LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)"); + LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu"); + LTTV_STATE_EXIT = g_quark_from_string("exiting"); + LTTV_STATE_WAIT = g_quark_from_string("wait for I/O"); + LTTV_STATE_RUN = g_quark_from_string("running"); + LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles"); + LTTV_STATE_PROCESSES = g_quark_from_string("processes"); + LTTV_STATE_PROCESS = g_quark_from_string("process"); + LTTV_STATE_EVENT = g_quark_from_string("event"); + LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states"); + LTTV_STATE_TIME = g_quark_from_string("time"); + LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks"); +} + +void lttv_state_destroy() +{ +} + + + + diff --git a/ltt/branches/poly/lttv/mainLib/stats.c b/ltt/branches/poly/lttv/mainLib/stats.c new file mode 100644 index 00000000..4265853d --- /dev/null +++ b/ltt/branches/poly/lttv/mainLib/stats.c @@ -0,0 +1,1180 @@ + +#include +#include +#include +#include +#include + +#define BUF_SIZE 256 + +GQuark + LTTV_STATS_PROCESS_UNKNOWN, + LTTV_STATS_PROCESSES, + LTTV_STATS_CPU, + LTTV_STATS_MODE_TYPES, + LTTV_STATS_MODES, + LTTV_STATS_SUBMODES, + LTTV_STATS_EVENT_TYPES, + LTTV_STATS_CPU_TIME, + LTTV_STATS_ELAPSED_TIME, + LTTV_STATS_EVENTS, + LTTV_STATS_EVENTS_COUNT; + +static GQuark + LTTV_STATS_BEFORE_HOOKS, + LTTV_STATS_AFTER_HOOKS; + +static void remove_all_processes(GHashTable *processes); + +static void +find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu, + GQuark mode, GQuark sub_mode, LttvAttribute **events_tree, + LttvAttribute **event_types_tree); + +static void +init(LttvTracesetStats *self, LttvTraceset *ts) +{ + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTraceStats *tcs; + + LttvTracefileContext *tfc; + + LttvTracefileStats *tfcs; + + LttTime timestamp = {0,0}; + + LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> + init((LttvTracesetContext *)self, ts); + + self->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + nb_trace = lttv_traceset_number(ts); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); + tcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfcs = LTTV_TRACEFILE_STATS(tc->control_tracefiles[j]); + } + else { + tfcs = LTTV_TRACEFILE_STATS(tc->per_cpu_tracefiles[j - nb_control]); + } + + tfcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN, + tfcs->parent.cpu_name, LTTV_STATE_MODE_UNKNOWN, + LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree, + &tfcs->current_event_types_tree); + } + } +} + + +static void +fini(LttvTracesetStats *self) +{ + guint i, j, nb_trace, nb_tracefile; + + LttvTraceset *ts; + + LttvTraceContext *tc; + + LttvTraceStats *tcs; + + LttvTracefileContext *tfc; + + LttvTracefileStats *tfcs; + + LttTime timestamp = {0,0}; + + lttv_attribute_recursive_free(self->stats); + ts = self->parent.parent.ts; + nb_trace = lttv_traceset_number(ts); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); + lttv_attribute_recursive_free(tcs->stats); + + nb_tracefile = ltt_trace_control_tracefile_number(tc->t); + for(j = 0 ; j < nb_tracefile ; j++) { + tfcs = (LttvTracefileStats *)tfc = tc->control_tracefiles[j]; + lttv_attribute_recursive_free(tfcs->stats); + tfcs->current_events_tree = NULL; + tfcs->current_event_types_tree = NULL; + } + + nb_tracefile = ltt_trace_per_cpu_tracefile_number(tc->t); + for(j = 0 ; j < nb_tracefile ; j++) { + tfcs = (LttvTracefileStats *)tfc = tc->per_cpu_tracefiles[j]; + lttv_attribute_recursive_free(tfcs->stats); + tfcs->current_events_tree = NULL; + tfcs->current_event_types_tree = NULL; + } + } + LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> + fini((LttvTracesetContext *)self); +} + + +static LttvTracesetContext * +new_traceset_context(LttvTracesetContext *self) +{ + return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL)); +} + + +static LttvTraceContext * +new_trace_context(LttvTracesetContext *self) +{ + return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL)); +} + + +static LttvTracefileContext * +new_tracefile_context(LttvTracesetContext *self) +{ + return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL)); +} + + +static void +traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +traceset_stats_finalize (LttvTracesetStats *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +traceset_stats_class_init (LttvTracesetContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize; + klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init; + klass->fini = (void (*)(LttvTracesetContext *self))fini; + klass->new_traceset_context = new_traceset_context; + klass->new_trace_context = new_trace_context; + klass->new_tracefile_context = new_tracefile_context; +} + + +GType +lttv_traceset_stats_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracesetStatsClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) traceset_stats_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracesetContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) traceset_stats_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACESET_STATE_TYPE, "LttvTracesetStatsType", + &info, 0); + } + return type; +} + + +static void +trace_stats_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +trace_stats_finalize (LttvTraceStats *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +trace_stats_class_init (LttvTraceContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize; +} + + +GType +lttv_trace_stats_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTraceStatsClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) trace_stats_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTraceStats), + 0, /* n_preallocs */ + (GInstanceInitFunc) trace_stats_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACE_STATE_TYPE, + "LttvTraceStatsType", &info, 0); + } + return type; +} + + +static void +tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +tracefile_stats_finalize (LttvTracefileStats *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +tracefile_stats_class_init (LttvTracefileStatsClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize; +} + + +GType +lttv_tracefile_stats_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracefileStatsClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) tracefile_stats_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracefileStats), + 0, /* n_preallocs */ + (GInstanceInitFunc) tracefile_stats_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE, + "LttvTracefileStatsType", &info, 0); + } + return type; +} + + +static void +find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu, + GQuark mode, GQuark sub_mode, LttvAttribute **events_tree, + LttvAttribute **event_types_tree) +{ + LttvAttribute *a; + + LttvTraceStats *tcs = LTTV_TRACE_STATS(tfcs->parent.parent.t_context); + a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES); + a = lttv_attribute_find_subdir(a, tfcs->parent.process->pid_time); + a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU); + a = lttv_attribute_find_subdir(a, tfcs->parent.cpu_name); + a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES); + a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->t); + a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES); + a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->n); + *events_tree = a; + a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES); + *event_types_tree = a; +} + + +static void update_event_tree(LttvTracefileStats *tfcs) +{ + LttvExecutionState *es = tfcs->parent.process->state; + + find_event_tree(tfcs, tfcs->parent.process->pid_time, tfcs->parent.cpu_name, + es->t, es->n, &(tfcs->current_events_tree), + &(tfcs->current_event_types_tree)); +} + + +static void mode_change(LttvTracefileStats *tfcs) +{ + LttvAttributeValue cpu_time; + + LttTime delta; + + lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, + LTTV_TIME, &cpu_time); + delta = ltt_time_sub(tfcs->parent.parent.timestamp, + tfcs->parent.process->state->change); + *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta); +} + + +static void mode_end(LttvTracefileStats *tfcs) +{ + LttvAttributeValue elapsed_time, cpu_time; + + LttTime delta; + + lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME, + LTTV_TIME, &elapsed_time); + delta = ltt_time_sub(tfcs->parent.parent.timestamp, + tfcs->parent.process->state->entry); + *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta); + + lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, + LTTV_TIME, &cpu_time); + delta = ltt_time_sub(tfcs->parent.parent.timestamp, + tfcs->parent.process->state->change); + *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta); +} + + +static gboolean before_syscall_entry(void *hook_data, void *call_data) +{ + mode_change((LttvTracefileStats *)call_data); + return FALSE; +} + + +static gboolean after_syscall_entry(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_syscall_exit(void *hook_data, void *call_data) +{ + mode_end((LttvTracefileStats *)call_data); + return FALSE; +} + + +static gboolean after_syscall_exit(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_trap_entry(void *hook_data, void *call_data) +{ + mode_change((LttvTracefileStats *)call_data); + return FALSE; +} + + +static gboolean after_trap_entry(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_trap_exit(void *hook_data, void *call_data) +{ + mode_end((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean after_trap_exit(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_irq_entry(void *hook_data, void *call_data) +{ + mode_change((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean after_irq_entry(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_irq_exit(void *hook_data, void *call_data) +{ + mode_end((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean after_irq_exit(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_schedchange(void *hook_data, void *call_data) +{ + LttvTraceHook *h = (LttvTraceHook *)hook_data; + + LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data; + + guint pid_in, pid_out, state_out; + + LttvProcessState *process; + + pid_in = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f1); + pid_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f2); + state_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f3); + + /* compute the time for the process to schedule out */ + + mode_change(tfcs); + + /* get the information for the process scheduled in */ + + process = lttv_state_find_process(&(tfcs->parent), pid_in); + + find_event_tree(tfcs, process->pid_time, tfcs->parent.cpu_name, + process->state->t, process->state->n, &(tfcs->current_events_tree), + &(tfcs->current_event_types_tree)); + + /* compute the time waiting for the process to schedule in */ + + mode_change(tfcs); + return FALSE; +} + + +gboolean process_fork(void *hook_data, void *call_data) +{ + /* nothing to do for now */ + return FALSE; +} + + +gboolean process_exit(void *hook_data, void *call_data) +{ + /* We should probably exit all modes here or we could do that at + schedule out. */ + return FALSE; +} + + +gboolean every_event(void *hook_data, void *call_data) +{ + LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data; + + LttvAttributeValue v; + + /* The current branch corresponds to the tracefile/process/interrupt state. + Statistics are added within it, to count the number of events of this + type occuring in this context. A quark has been pre-allocated for each + event type and is used as name. */ + + lttv_attribute_find(tfcs->current_event_types_tree, + ((LttvTraceState *)(tfcs->parent.parent.t_context))-> + eventtype_names[ltt_event_eventtype_id(tfcs->parent.parent.e)], + LTTV_UINT, &v); + (*(v.v_uint))++; + return FALSE; +} + + +static gboolean +sum_stats(void *hook_data, void *call_data) +{ + LttvTracesetStats *tscs = (LttvTracesetStats *)call_data; + + LttvTraceStats *tcs; + + LttvTraceset *traceset = tscs->parent.parent.ts; + + LttvAttributeType type; + + LttvAttributeValue value; + + LttvAttributeName name; + + unsigned sum; + + int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode, + nb_event_type; + + LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, + *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, + *submode_tree, *event_types_tree, *mode_events_tree, + *cpu_events_tree, *process_modes_tree, *trace_cpu_tree, + *trace_modes_tree, *traceset_modes_tree; + + traceset_modes_tree = lttv_attribute_find_subdir(tscs->stats, + LTTV_STATS_MODES); + nb_trace = lttv_traceset_number(traceset); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); + main_tree = tcs->stats; + processes_tree = lttv_attribute_find_subdir(main_tree, + LTTV_STATS_PROCESSES); + trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES); + nb_process = lttv_attribute_get_number(processes_tree); + + for(j = 0 ; j < nb_process ; j++) { + type = lttv_attribute_get(processes_tree, j, &name, &value); + process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); + process_modes_tree = lttv_attribute_find_subdir(process_tree, + LTTV_STATS_MODES); + nb_cpu = lttv_attribute_get_number(cpus_tree); + + for(k = 0 ; k < nb_cpu ; k++) { + type = lttv_attribute_get(cpus_tree, k, &name, &value); + cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + mode_types_tree = lttv_attribute_find_subdir(cpu_tree, + LTTV_STATS_MODE_TYPES); + cpu_events_tree = lttv_attribute_find_subdir(cpu_tree, + LTTV_STATS_EVENTS); + trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU); + trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name); + nb_mode_type = lttv_attribute_get_number(mode_types_tree); + + for(l = 0 ; l < nb_mode_type ; l++) { + type = lttv_attribute_get(mode_types_tree, l, &name, &value); + mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + submodes_tree = lttv_attribute_find_subdir(mode_tree, + LTTV_STATS_SUBMODES); + mode_events_tree = lttv_attribute_find_subdir(mode_tree, + LTTV_STATS_EVENTS); + nb_submode = lttv_attribute_get_number(submodes_tree); + + for(m = 0 ; m < nb_submode ; m++) { + type = lttv_attribute_get(submodes_tree, m, &name, &value); + submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + event_types_tree = lttv_attribute_find_subdir(submode_tree, + LTTV_STATS_EVENT_TYPES); + nb_event_type = lttv_attribute_get_number(event_types_tree); + + sum = 0; + for(n = 0 ; n < nb_event_type ; n++) { + type = lttv_attribute_get(event_types_tree, n, &name, &value); + sum += *(value.v_uint); + } + lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT, + LTTV_UINT, &value); + *(value.v_uint) = sum; + lttv_attribute_recursive_add(mode_events_tree, submode_tree); + } + lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree); + } + lttv_attribute_recursive_add(process_modes_tree, cpu_tree); + lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree); + } + lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree); + } + lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree); + } + return FALSE; +} + + +lttv_stats_add_event_hooks(LttvTracesetStats *self) +{ + LttvTraceset *traceset = self->parent.parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttFacility *f; + + LttEventType *et; + + LttvTraceStats *ts; + + LttvTracefileStats *tfs; + + void *hook_data; + + GArray *hooks, *before_hooks, *after_hooks; + + LttvTraceHook hook; + + LttvAttributeValue val; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = (LttvTraceStats *)self->parent.parent.traces[i]; + + /* Find the eventtype id for the following events and register the + associated by id hooks. */ + + hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); + g_array_set_size(hooks, 7); + + lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry", + "syscall_id", NULL, NULL, before_syscall_entry, + &g_array_index(hooks, LttvTraceHook, 0)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL, + NULL, NULL, before_syscall_exit, + &g_array_index(hooks, LttvTraceHook, 1)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id", + NULL, NULL, before_trap_entry, + &g_array_index(hooks, LttvTraceHook, 2)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL, + NULL, before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id", + NULL, NULL, before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL, + NULL, before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "schedchange", "in", + "out", "out_state", before_schedchange, + &g_array_index(hooks, LttvTraceHook, 6)); + + before_hooks = hooks; + + hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); + g_array_set_size(hooks, 8); + + lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry", + "syscall_id", NULL, NULL, after_syscall_entry, + &g_array_index(hooks, LttvTraceHook, 0)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL, + NULL, NULL, after_syscall_exit, + &g_array_index(hooks, LttvTraceHook, 1)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id", + NULL, NULL, after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL, + NULL, after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id", + NULL, NULL, after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL, + NULL, after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "process_fork", + "child_pid", NULL, NULL, process_fork, + &g_array_index(hooks, LttvTraceHook, 6)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "process_exit", NULL, + NULL, NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 7)); + + after_hooks = hooks; + + /* Add these hooks to each before_event_by_id hooks list */ + + nb_control = ltt_trace_control_tracefile_number(ts->parent.parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.control_tracefiles[j]); + } + else { + tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.per_cpu_tracefiles[ + j-nb_control]); + } + + lttv_hooks_add(tfs->parent.parent.after_event, every_event, NULL); + + for(k = 0 ; k < before_hooks->len ; k++) { + hook = g_array_index(before_hooks, LttvTraceHook, k); + lttv_hooks_add(lttv_hooks_by_id_find( + tfs->parent.parent.before_event_by_id, + hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k)); + } + for(k = 0 ; k < after_hooks->len ; k++) { + hook = g_array_index(after_hooks, LttvTraceHook, k); + lttv_hooks_add(lttv_hooks_by_id_find( + tfs->parent.parent.after_event_by_id, + hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k)); + } + } + lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS, + LTTV_POINTER, &val); + *(val.v_pointer) = before_hooks; + lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS, + LTTV_POINTER, &val); + *(val.v_pointer) = after_hooks; + } + lttv_hooks_add(self->parent.parent.after, sum_stats, NULL); +} + + +lttv_stats_remove_event_hooks(LttvTracesetStats *self) +{ + LttvTraceset *traceset = self->parent.parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceStats *ts; + + LttvTracefileStats *tfs; + + void *hook_data; + + GArray *before_hooks, *after_hooks; + + LttvTraceHook hook; + + LttvAttributeValue val; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = LTTV_TRACE_STATS(self->parent.parent.traces[i]); + lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS, + LTTV_POINTER, &val); + before_hooks = *(val.v_pointer); + lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS, + LTTV_POINTER, &val); + after_hooks = *(val.v_pointer); + + /* Add these hooks to each before_event_by_id hooks list */ + + nb_control = ltt_trace_control_tracefile_number(ts->parent.parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.control_tracefiles[j]); + } + else { + tfs =LTTV_TRACEFILE_STATS(ts->parent.parent.per_cpu_tracefiles[ + j-nb_control]); + } + + lttv_hooks_remove_data(tfs->parent.parent.after_event, every_event, + NULL); + + for(k = 0 ; k < before_hooks->len ; k++) { + hook = g_array_index(before_hooks, LttvTraceHook, k); + lttv_hooks_remove_data( + lttv_hooks_by_id_find(tfs->parent.parent.before_event_by_id, + hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k)); + } + for(k = 0 ; k < after_hooks->len ; k++) { + hook = g_array_index(after_hooks, LttvTraceHook, k); + lttv_hooks_remove_data( + lttv_hooks_by_id_find(tfs->parent.parent.after_event_by_id, + hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k)); + } + } + g_critical("lttv_stats_remove_event_hooks()"); + g_array_free(before_hooks, TRUE); + g_array_free(after_hooks, TRUE); + } + lttv_hooks_remove_data(self->parent.parent.after, sum_stats, NULL); +} + + +void lttv_stats_init(int argc, char **argv) +{ + LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process"); + LTTV_STATS_PROCESSES = g_quark_from_string("processes"); + LTTV_STATS_CPU = g_quark_from_string("cpu"); + LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types"); + LTTV_STATS_MODES = g_quark_from_string("modes"); + LTTV_STATS_SUBMODES = g_quark_from_string("submodes"); + LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types"); + LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time"); + LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time"); + LTTV_STATS_EVENTS = g_quark_from_string("events"); + LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count"); + LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks"); + LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks"); +} + +void lttv_stats_destroy() +{ +} + +void lttv_stats_save_attribute(LttvAttribute *attr, char *indent, FILE * fp) +{ + LttvAttributeType type; + LttvAttributeValue value; + LttvAttributeName name; + char type_value[BUF_SIZE]; + int i, nb_attr, flag; + + nb_attr = lttv_attribute_get_number(attr); + for(i=0;itv_sec, + value.v_time->tv_nsec); + break; + case LTTV_POINTER: + sprintf(type_value, "POINTER\0"); + break; + case LTTV_STRING: + sprintf(type_value, "%s\0", *value.v_string); + break; + default: + flag = 0; + break; + } + if(flag == 0) continue; + fprintf(fp,"%s",indent,type,g_quark_to_string(name)); + fprintf(fp,"%s",type_value); + fprintf(fp," \n"); + } + +} + +void lttv_stats_save_statistics(LttvTracesetStats *self) +{ + LttvTracesetStats *tscs = self; + LttvTraceStats *tcs; + LttvTraceset *traceset = tscs->parent.parent.ts; + LttvAttributeType type; + LttvAttributeValue value; + LttvAttributeName name; + + char filename[BUF_SIZE]; + FILE * fp; + char indent[10][24]= {" ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + }; + + + int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode; + + LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, + *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, + *submode_tree, *event_types_tree; + + nb_trace = lttv_traceset_number(traceset); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); + + filename[0] = '\0'; + strcat(filename,ltt_trace_name(tcs->parent.parent.t)); + strcat(filename,"/statistics.xml"); + fp = fopen(filename,"w"); + if(!fp){ + g_warning("can not open the file %s for saving statistics\n", filename); + exit(1); + } + + main_tree = tcs->stats; + processes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_PROCESSES); + nb_process = lttv_attribute_get_number(processes_tree); + + fprintf(fp, " \n",g_quark_to_string(LTTV_STATS_PROCESSES)); //root NODE + + for(j = 0 ; j < nb_process ; j++) { + type = lttv_attribute_get(processes_tree, j, &name, &value); + process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + fprintf(fp,"%s \n",indent[0],g_quark_to_string(name)); //process NODE + lttv_stats_save_attribute(process_tree,indent[1], fp); + fprintf(fp,"%s \n", indent[1],g_quark_to_string(LTTV_STATS_CPU)); //cpus NODE + + cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); + nb_cpu = lttv_attribute_get_number(cpus_tree); + + for(k = 0 ; k < nb_cpu ; k++) { + type = lttv_attribute_get(cpus_tree, k, &name, &value); + cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + fprintf(fp,"%s \n",indent[2],g_quark_to_string(name)); //cpu NODE + lttv_stats_save_attribute(cpu_tree,indent[3], fp); + fprintf(fp,"%s \n",indent[3],g_quark_to_string(LTTV_STATS_MODE_TYPES)); //mode_types NODE + + mode_types_tree = lttv_attribute_find_subdir(cpu_tree,LTTV_STATS_MODE_TYPES); + nb_mode_type = lttv_attribute_get_number(mode_types_tree); + + for(l = 0 ; l < nb_mode_type ; l++) { + type = lttv_attribute_get(mode_types_tree, l, &name, &value); + mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + fprintf(fp,"%s \n",indent[4],g_quark_to_string(name)); //mode NODE + lttv_stats_save_attribute(mode_tree,indent[5], fp); + fprintf(fp,"%s \n",indent[5],g_quark_to_string(LTTV_STATS_SUBMODES)); //sub_modes NODE + + submodes_tree = lttv_attribute_find_subdir(mode_tree,LTTV_STATS_SUBMODES); + nb_submode = lttv_attribute_get_number(submodes_tree); + + for(m = 0 ; m < nb_submode ; m++) { + type = lttv_attribute_get(submodes_tree, m, &name, &value); + submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + fprintf(fp,"%s \n",indent[6],g_quark_to_string(name)); //sub_mode NODE + lttv_stats_save_attribute(submode_tree,indent[7], fp); + fprintf(fp,"%s \n",indent[7],g_quark_to_string(LTTV_STATS_EVENT_TYPES)); //event_types NODE + + event_types_tree = lttv_attribute_find_subdir(submode_tree, LTTV_STATS_EVENT_TYPES); + lttv_stats_save_attribute(event_types_tree,indent[8], fp); + + fprintf(fp,"%s \n",indent[7]); //event_types NODE + fprintf(fp,"%s \n",indent[6]); //sub_mode NODE + } + fprintf(fp,"%s \n",indent[5]); //sub_modes NODE + fprintf(fp,"%s \n",indent[4]); //mode NODE + } + fprintf(fp,"%s \n",indent[3]); //mode_type NODE + fprintf(fp,"%s \n",indent[2]); //cpu NODE + } + fprintf(fp,"%s \n",indent[1]); //cpus NODE + fprintf(fp,"%s \n", indent[0]); //process NODE + } + fprintf(fp, "\n"); //root NODE + fclose(fp); + } +} + + +/* Functions to parse statistic.xml file (using glib xml parser) */ + +typedef struct _ParserStruct{ + GPtrArray * attribute; + LttvAttributeType type; + LttvAttributeName name; +} ParserStruct; + +static void stats_parser_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + ParserStruct * parser = (ParserStruct *)user_data; + int len; + LttvAttributeType type; + LttvAttributeName name; + LttvAttribute * parent_att, *new_att; + + len = parser->attribute->len; + parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); + + if(strcmp("NODE", element_name) == 0){ + type = LTTV_GOBJECT; + name = g_quark_from_string(attribute_values[0]); + new_att = lttv_attribute_find_subdir(parent_att,name); + g_ptr_array_add(parser->attribute, (gpointer)new_att); + }else if(strcmp("VALUE", element_name) == 0){ + parser->type = (LttvAttributeType) atoi(attribute_values[0]); + parser->name = g_quark_from_string(attribute_values[1]); + }else{ + g_warning("This is not statistics.xml file\n"); + exit(1); + } +} + +static void stats_parser_end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + ParserStruct * parser = (ParserStruct *)user_data; + int len; + LttvAttribute * parent_att; + + len = parser->attribute->len; + parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); + + if(strcmp("NODE", element_name) == 0){ + g_ptr_array_remove_index(parser->attribute, len-1); + }else if(strcmp("VALUE", element_name) == 0){ + }else{ + g_warning("This is not statistics.xml file\n"); + exit(1); + } + +} + +static void stats_parser_characters (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + ParserStruct * parser = (ParserStruct *)user_data; + LttvAttributeValue value; + int len; + LttvAttribute * parent_att; + char *pos; + + pos = (char*)text; + for(len=0;lenattribute->len; + parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); + if(!lttv_attribute_find(parent_att,parser->name, parser->type, &value)){ + g_warning("can not find value\n"); + exit(1); + } + + switch(parser->type) { + case LTTV_INT: + *value.v_int = atoi(text); + break; + case LTTV_UINT: + *value.v_uint = (unsigned)atoi(text); + break; + case LTTV_LONG: + *value.v_long = atol(text); + break; + case LTTV_ULONG: + *value.v_ulong = (unsigned long)atol(text); + break; + case LTTV_FLOAT: + *value.v_float = atof(text); + break; + case LTTV_DOUBLE: + *value.v_float = atof(text); + break; + case LTTV_TIME: + pos = strrchr(text,'.'); + if(pos){ + *pos = '\0'; + pos++; + value.v_time->tv_sec = atol(text); + value.v_time->tv_nsec = atol(pos); + }else{ + g_warning("The time value format is wrong\n"); + exit(1); + } + break; + case LTTV_POINTER: + break; + case LTTV_STRING: + *value.v_string = g_strdup(text); + break; + default: + break; + } + +} + +gboolean lttv_stats_load_statistics(LttvTracesetStats *self) +{ + FILE * fp; + char buf[BUF_SIZE]; + LttvTracesetStats *tscs = self; + LttvTraceStats *tcs; + LttvTraceset *traceset = tscs->parent.parent.ts; + char filename[BUF_SIZE]; + + GMarkupParseContext * context; + GError * error; + GMarkupParser markup_parser = + { + stats_parser_start_element, + stats_parser_end_element, + stats_parser_characters, + NULL, /* passthrough */ + NULL /* error */ + }; + + int i, nb_trace; + LttvAttribute *main_tree; + ParserStruct a_parser_struct; + a_parser_struct.attribute = g_ptr_array_new(); + + nb_trace = lttv_traceset_number(traceset); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); + + filename[0] = '\0'; + strcat(filename,ltt_trace_name(tcs->parent.parent.t)); + strcat(filename,"/statistics.xml"); + fp = fopen(filename,"r"); + if(!fp){ + g_warning("can not open the file %s for reading statistics\n", filename); + return FALSE; + } + + main_tree = tcs->stats; + g_ptr_array_add(a_parser_struct.attribute,(gpointer)main_tree); + + context = g_markup_parse_context_new(&markup_parser, 0, (gpointer)&a_parser_struct, NULL); + + while(fgets(buf,BUF_SIZE, fp) != NULL){ + if(!g_markup_parse_context_parse(context, buf, BUF_SIZE, &error)){ + g_warning("Can not parse xml file: \n%s\n", error->message); + exit(1); + } + } + fclose(fp); + } + + sum_stats(NULL, (void *)self); + + return TRUE; +} diff --git a/ltt/branches/poly/lttv/mainLib/traceset.c b/ltt/branches/poly/lttv/mainLib/traceset.c new file mode 100644 index 00000000..ce96b99a --- /dev/null +++ b/ltt/branches/poly/lttv/mainLib/traceset.c @@ -0,0 +1,171 @@ + +#include +#include + +/* 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 _LttvTraceset { + char * filename; + GPtrArray *traces; + LttvAttribute *a; +}; + + +struct _LttvTrace { + LttTrace *t; + LttvAttribute *a; + guint ref_count; +}; + + +LttvTraceset *lttv_traceset_new() +{ + LttvTraceset *s; + + s = g_new(LttvTraceset, 1); + s->filename = NULL; + s->traces = g_ptr_array_new(); + s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + return s; +} + +char * lttv_traceset_name(LttvTraceset * s) +{ + return s->filename; +} + +LttvTrace *lttv_trace_new(LttTrace *t) +{ + LttvTrace *new_trace; + + new_trace = g_new(LttvTrace, 1); + new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + new_trace->t = t; + new_trace->ref_count = 0; + return new_trace; +} + + +LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig) +{ + int i; + LttvTraceset *s; + LttvTrace * trace; + + s = g_new(LttvTraceset, 1); + s->filename = NULL; + s->traces = g_ptr_array_new(); + for(i=0;itraces->len;i++) + { + trace = g_ptr_array_index(s_orig->traces, i); + trace->ref_count++; + + /*CHECK this used ltt_trace_copy while it may not be needed. Need to + define how traces and tracesets are shared */ + g_ptr_array_add( + s->traces, + g_ptr_array_index(s_orig->traces, i)); + } + s->a = LTTV_ATTRIBUTE(lttv_iattribute_deep_copy(LTTV_IATTRIBUTE(s_orig->a))); + return s; +} + + +LttvTraceset *lttv_traceset_load(const gchar *filename) +{ + LttvTraceset *s = g_new(LttvTraceset,1); + FILE *tf; + + s->filename = g_strdup(filename); + tf = fopen(filename,"r"); + + g_critical("NOT IMPLEMENTED : load traceset data from a XML file"); + + fclose(tf); + return s; +} + +gint lttv_traceset_save(LttvTraceset *s) +{ + FILE *tf; + + tf = fopen(s->filename, "w"); + + g_critical("NOT IMPLEMENTED : save traceset data in a XML file"); + + fclose(tf); + return 0; +} + +void lttv_traceset_destroy(LttvTraceset *s) +{ + g_ptr_array_free(s->traces, TRUE); + g_object_unref(s->a); + g_free(s); +} + +void lttv_trace_destroy(LttvTrace *t) +{ + g_object_unref(t->a); + g_free(t); +} + + +void lttv_traceset_add(LttvTraceset *s, LttvTrace *t) +{ + t->ref_count++; + g_ptr_array_add(s->traces, t); +} + + +unsigned lttv_traceset_number(LttvTraceset *s) +{ + return s->traces->len; +} + + +LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i) +{ + g_assert(s->traces->len > i); + return ((LttvTrace *)s->traces->pdata[i]); +} + + +void lttv_traceset_remove(LttvTraceset *s, unsigned i) +{ + LttvTrace * t; + g_assert(s->traces->len > i); + t = (LttvTrace *)s->traces->pdata[i]; + t->ref_count--; + g_ptr_array_remove_index(s->traces, i); +} + + +/* A set of attributes is attached to each trace set, trace and tracefile + to store user defined data as needed. */ + +LttvAttribute *lttv_traceset_attribute(LttvTraceset *s) +{ + return s->a; +} + + +LttvAttribute *lttv_trace_attribute(LttvTrace *t) +{ + return t->a; +} + + +LttTrace *lttv_trace(LttvTrace *t) +{ + return t->t; +} + +guint lttv_trace_get_ref_number(LttvTrace * t) +{ + return t->ref_count; +} diff --git a/ltt/branches/poly/lttv/module.c b/ltt/branches/poly/lttv/module.c deleted file mode 100644 index e225992a..00000000 --- a/ltt/branches/poly/lttv/module.c +++ /dev/null @@ -1,302 +0,0 @@ - -/* module.c : Implementation of the module loading/unloading mechanism. - * - */ - -#include - -#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) -#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) - -struct _LttvModule -{ - GModule *module; - guint ref_count; - guint load_count; - GPtrArray *dependents; -}; - - -/* Table of loaded modules and paths where to search for modules */ - -static GHashTable *modules = NULL; - -static GPtrArray *modulesPaths = NULL; - -static void lttv_module_unload_all(); - - -void lttv_module_init(int argc, char **argv) -{ - g_info("Init module.c"); - modules = g_hash_table_new(g_str_hash, g_str_equal); - modulesPaths = g_ptr_array_new(); -} - - -void lttv_module_destroy() -{ - int i; - - g_info("Destroy module.c"); - - /* Unload all modules */ - lttv_module_unload_all(); - - /* Free the modules paths pointer array as well as the elements */ - for(i = 0; i < modulesPaths->len ; i++) { - g_free(modulesPaths->pdata[i]); - } - g_ptr_array_free(modulesPaths,TRUE) ; - modulesPaths = NULL; - - /* destroy the hash table */ - g_hash_table_destroy(modules) ; - modules = NULL; -} - - -/* Add a new pathname to the modules loading search path */ - -void lttv_module_path_add(const char *name) -{ - g_info("Add module path %s", name); - g_ptr_array_add(modulesPaths,(char*)g_strdup(name)); -} - - -static LttvModule * -module_load(const char *name, int argc, char **argv) -{ - GModule *gm; - - LttvModule *m; - - int i; - - char *pathname; - - const char *module_name; - - LttvModuleInit init_function; - - g_info("Load module %s", name); - - /* Try to find the module along all the user specified paths */ - - for(i = 0 ; i < modulesPaths->len ; i++) { - pathname = g_module_build_path(modulesPaths->pdata[i],name); - g_info("Try path %s", pathname); - gm = g_module_open(pathname,0); - g_free(pathname); - - if(gm != NULL) break; - g_info("Trial failed, %s", g_module_error()); - } - - /* Try the default system path */ - - if(gm == NULL) { - pathname = g_module_build_path(NULL,name); - g_info("Try default path"); - gm = g_module_open(pathname,0); - g_free(pathname); - } - - /* Module cannot be found */ - if(gm == NULL) { - g_info("Trial failed, %s", g_module_error()); - g_info("Failed to load %s", name); - return NULL; - } - - /* Check if the module was already opened using the hopefully canonical name - returned by g_module_name. */ - - module_name = g_module_name(gm); - - m = g_hash_table_lookup(modules, module_name); - - if(m == NULL) { - g_info("Module %s (%s) loaded, call its init function", name, module_name); - - /* Module loaded for the first time. Insert it in the table and call the - init function if any. */ - - m = g_new(LttvModule, 1); - m->module = gm; - m->ref_count = 0; - m->load_count = 0; - m->dependents = g_ptr_array_new(); - g_hash_table_insert(modules, (gpointer)module_name, m); - - if(!g_module_symbol(gm, "init", (gpointer)&init_function)) { - g_warning("module %s (%s) has no init function", name, pathname); - } - else init_function(m, argc, argv); - } - else { - - /* Module was already opened, check that it really is the same and - undo the extra g_module_open */ - - g_info("Module %s (%s) was already loaded, no need to call init function", - name, module_name); - if(m->module != gm) g_error("Two gmodules with the same pathname"); - g_module_close(gm); - } - - m->ref_count++; - return m; -} - - -LttvModule * -lttv_module_load(const char *name, int argc, char **argv) -{ - g_info("Load module %s explicitly", name); - LttvModule *m = module_load(name, argc, argv); - if(m != NULL) m->load_count++; - return m; -} - - -LttvModule * -lttv_module_require(LttvModule *m, const char *name, int argc, char **argv) -{ - LttvModule *module; - - g_info("Load module %s, as %s is a dependent requiring it", name, - g_module_name(m->module)); - module = module_load(name, argc, argv); - if(module != NULL) g_ptr_array_add(module->dependents, m); - return module; -} - - -static void module_unload(LttvModule *m) -{ - LttvModuleDestroy destroy_function; - - char *pathname; - - guint i, len; - - /* Decrement the reference count */ - - g_info("Unload module %s", g_module_name(m->module)); - m->ref_count--; - if(m->ref_count > 0) { - g_info("Module usage count decremented to %d", m->ref_count); - return; - } - /* We really have to unload the module, first unload its dependents */ - - len = m->dependents->len; - g_info("Unload dependent modules"); - - for(i = 0 ; i < len ; i++) { - module_unload(m->dependents->pdata[i]); - } - - if(len != m->dependents->len) g_error("dependents list modified"); - - /* Unload the module itself */ - - g_info("Call the destroy function and unload the module"); - if(!g_module_symbol(m->module, "destroy", (gpointer)&destroy_function)) { - g_warning("module (%s) has no destroy function", pathname); - } - else destroy_function(); - - g_hash_table_remove(modules, g_module_name(m->module)); - g_ptr_array_free(m->dependents, TRUE); - g_module_close(m->module); - g_free(m); -} - - -void lttv_module_unload(LttvModule *m) -{ - g_info("Explicitly unload module %s", g_module_name(m->module)); - if(m->load_count <= 0) { - g_error("more unload than load (%s)", g_module_name(m->module)); - return; - } - m->load_count--; - module_unload(m); -} - - -static void -list_modules(gpointer key, gpointer value, gpointer user_data) -{ - g_ptr_array_add((GPtrArray *)user_data, value); -} - - -LttvModule ** -lttv_module_list(guint *nb) -{ - GPtrArray *list = g_ptr_array_new(); - - LttvModule **array; - - g_hash_table_foreach(modules, list_modules, list); - *nb = list->len; - array = (LttvModule **)list->pdata; - g_ptr_array_free(list, FALSE); - return array; -} - - -LttvModule ** -lttv_module_info(LttvModule *m, const char **name, - guint *ref_count, guint *load_count, guint *nb_dependents) -{ - guint i, len = m->dependents->len; - - LttvModule **array = g_new(LttvModule *, len); - - *name = g_module_name(m->module); - *ref_count = m->ref_count; - *load_count = m->load_count; - *nb_dependents = len; - for(i = 0 ; i < len ; i++) array[i] = m->dependents->pdata[i]; - return array; -} - -char * -lttv_module_name(LttvModule *m) -{ - return g_module_name(m->module); -} - -static void -list_independent(gpointer key, gpointer value, gpointer user_data) -{ - LttvModule *m = (LttvModule *)value; - - if(m->load_count > 0) g_ptr_array_add((GPtrArray *)user_data, m); -} - - -void -lttv_module_unload_all() -{ - guint i; - - LttvModule *m; - - GPtrArray *independent_modules = g_ptr_array_new(); - - g_hash_table_foreach(modules, list_independent, independent_modules); - - for(i = 0 ; i < independent_modules->len ; i++) { - m = (LttvModule *)independent_modules->pdata[i]; - while(m->load_count > 0) lttv_module_unload(m); - } - - g_ptr_array_free(independent_modules, TRUE); - if(g_hash_table_size(modules) != 0) g_warning("cannot unload all modules"); -} diff --git a/ltt/branches/poly/lttv/modules/text/batchAnalysis.c b/ltt/branches/poly/lttv/modules/text/batchAnalysis.c new file mode 100644 index 00000000..62703429 --- /dev/null +++ b/ltt/branches/poly/lttv/modules/text/batchAnalysis.c @@ -0,0 +1,182 @@ +/* This module inserts a hook in the program main loop. This hook processes + all the events in the main tracefile. */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static LttvTraceset *traceset; + +static LttvHooks + *before_traceset, + *after_traceset, + *before_trace, + *after_trace, + *before_tracefile, + *after_tracefile, + *before_event, + *after_event, + *main_hooks; + +static char *a_trace; + +static gboolean a_stats; + +void lttv_trace_option(void *hook_data) +{ + LttTrace *trace; + + trace = ltt_trace_open(a_trace); + if(trace == NULL) g_critical("cannot open trace %s", a_trace); + lttv_traceset_add(traceset, lttv_trace_new(trace)); +} + + +static gboolean process_traceset(void *hook_data, void *call_data) +{ + LttvTracesetStats *tscs; + + LttvTracesetContext *tc; + + LttTime start, end; + + g_info("BatchAnalysis begin process traceset"); + + tscs = g_object_new(LTTV_TRACESET_STATS_TYPE, NULL); + tc = &tscs->parent.parent; + + g_info("BatchAnalysis initialize context"); + + lttv_context_init(tc, traceset); + lttv_state_add_event_hooks(&tscs->parent); + if(a_stats) lttv_stats_add_event_hooks(tscs); + + lttv_traceset_context_add_hooks(tc, + before_traceset, after_traceset, NULL, before_trace, after_trace, + NULL, before_tracefile, after_tracefile, NULL, before_event, after_event); + + start.tv_sec = 0; + start.tv_nsec = 0; + end.tv_sec = G_MAXULONG; + end.tv_nsec = G_MAXULONG; + + g_info("BatchAnalysis process traceset"); + + lttv_process_traceset_seek_time(tc, start); + lttv_process_traceset(tc, end, G_MAXULONG); + + g_info("BatchAnalysis destroy context"); + + lttv_traceset_context_remove_hooks(tc, + before_traceset, after_traceset, NULL, before_trace, after_trace, + NULL, before_tracefile, after_tracefile, NULL, before_event, after_event); + lttv_state_remove_event_hooks(&tscs->parent); + if(a_stats) lttv_stats_remove_event_hooks(tscs); + lttv_context_fini(tc); + g_object_unref(tscs); + + g_info("BatchAnalysis end process traceset"); +} + + +G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv) +{ + LttvAttributeValue value; + + LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); + + g_info("Init batchAnalysis.c"); + + lttv_option_add("trace", 't', + "add a trace to the trace set to analyse", + "pathname of the directory containing the trace", + LTTV_OPT_STRING, &a_trace, lttv_trace_option, NULL); + + a_stats = FALSE; + lttv_option_add("stats", 's', + "write the traceset and trace statistics", + "", + LTTV_OPT_NONE, &a_stats, NULL, NULL); + + + traceset = lttv_traceset_new(); + + before_traceset = lttv_hooks_new(); + after_traceset = lttv_hooks_new(); + before_trace = lttv_hooks_new(); + after_trace = lttv_hooks_new(); + before_tracefile = lttv_hooks_new(); + after_tracefile = lttv_hooks_new(); + before_event = lttv_hooks_new(); + after_event = lttv_hooks_new(); + + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/before", + LTTV_POINTER, &value)); + *(value.v_pointer) = before_traceset; + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/after", + LTTV_POINTER, &value)); + *(value.v_pointer) = after_traceset; + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/before", + LTTV_POINTER, &value)); + *(value.v_pointer) = before_trace; + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/after", + LTTV_POINTER, &value)); + *(value.v_pointer) = after_trace; + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/before", + LTTV_POINTER, &value)); + *(value.v_pointer) = before_tracefile; + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/after", + LTTV_POINTER, &value)); + *(value.v_pointer) = after_tracefile; + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/before", + LTTV_POINTER, &value)); + *(value.v_pointer) = before_event; + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/after", + LTTV_POINTER, &value)); + *(value.v_pointer) = after_event; + + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/before", + LTTV_POINTER, &value)); + g_assert((main_hooks = *(value.v_pointer)) != NULL); + lttv_hooks_add(main_hooks, process_traceset, NULL); +} + + +G_MODULE_EXPORT void destroy() +{ + guint i, nb; + + LttvTrace *trace; + + g_info("Destroy batchAnalysis.c"); + + lttv_option_remove("trace"); + lttv_option_remove("stats"); + + lttv_hooks_destroy(before_traceset); + lttv_hooks_destroy(after_traceset); + lttv_hooks_destroy(before_trace); + lttv_hooks_destroy(after_trace); + lttv_hooks_destroy(before_tracefile); + lttv_hooks_destroy(after_tracefile); + lttv_hooks_destroy(before_event); + lttv_hooks_destroy(after_event); + lttv_hooks_remove_data(main_hooks, process_traceset, NULL); + + nb = lttv_traceset_number(traceset); + for(i = 0 ; i < nb ; i++) { + trace = lttv_traceset_get(traceset, i); + ltt_trace_close(lttv_trace(trace)); + lttv_trace_destroy(trace); + } + + lttv_traceset_destroy(traceset); +} + diff --git a/ltt/branches/poly/lttv/modules/text/textDump.c b/ltt/branches/poly/lttv/modules/text/textDump.c new file mode 100644 index 00000000..24b266a2 --- /dev/null +++ b/ltt/branches/poly/lttv/modules/text/textDump.c @@ -0,0 +1,405 @@ +/* The text dump facility needs to print headers before the trace set and + before each trace, to print each event, and to print statistics + after each trace. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static gboolean + a_field_names, + a_state, + a_cpu_stats, + a_process_stats; + +static char + *a_file_name = NULL; + +static LttvHooks + *before_traceset, + *after_traceset, + *before_trace, + *before_event; + + +void print_field(LttEvent *e, LttField *f, GString *s, gboolean field_names) { + + LttType *type; + + LttField *element; + + char *name; + + 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, + ltt_event_get_unsigned(e,f)-1)); + 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, field_names); + } + 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); + if(field_names) { + ltt_type_member_type(type, i, &name); + g_string_append_printf(s, " %s = ", name); + } + print_field(e, element, s, field_names); + } + g_string_append_printf(s, " }"); + break; + } +} + + +void lttv_event_to_string(LttEvent *e, LttTracefile *tf, GString *s, + gboolean mandatory_fields, gboolean field_names, LttvTracefileState *tfs) +{ + LttFacility *facility; + + LttEventType *event_type; + + LttType *type; + + LttField *field; + + LttTime time; + + g_string_set_size(s,0); + + facility = ltt_event_facility(e); + event_type = 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.%09ld (%s)", + ltt_facility_name(facility), + ltt_eventtype_name(event_type), (long)time.tv_sec, time.tv_nsec, + g_quark_to_string(tfs->cpu_name)); + /* Print the process id and the state/interrupt type of the process */ + g_string_append_printf(s,", %u, %u, %s", tfs->process->pid, + tfs->process->ppid, + g_quark_to_string(tfs->process->state->t)); + } + + if(field) + print_field(e, field, s, field_names); +} + + +static void +print_tree(FILE *fp, GString *indent, LttvAttribute *tree) +{ + int i, nb, saved_length; + + LttvAttribute *subtree; + + LttvAttributeName name; + + LttvAttributeValue value; + + LttvAttributeType type; + + nb = lttv_attribute_get_number(tree); + for(i = 0 ; i < nb ; i++) { + type = lttv_attribute_get(tree, i, &name, &value); + fprintf(fp, "%s%s: ", indent->str, g_quark_to_string(name)); + + switch(type) { + case LTTV_INT: + fprintf(fp, "%d\n", *value.v_int); + break; + case LTTV_UINT: + fprintf(fp, "%u\n", *value.v_uint); + break; + case LTTV_LONG: + fprintf(fp, "%ld\n", *value.v_long); + break; + case LTTV_ULONG: + fprintf(fp, "%lu\n", *value.v_ulong); + break; + case LTTV_FLOAT: + fprintf(fp, "%f\n", (double)*value.v_float); + break; + case LTTV_DOUBLE: + fprintf(fp, "%f\n", *value.v_double); + break; + case LTTV_TIME: + fprintf(fp, "%10u.%09u\n", value.v_time->tv_sec, + value.v_time->tv_nsec); + break; + case LTTV_POINTER: + fprintf(fp, "POINTER\n"); + break; + case LTTV_STRING: + fprintf(fp, "%s\n", *value.v_string); + break; + case LTTV_GOBJECT: + if(LTTV_IS_ATTRIBUTE(*(value.v_gobject))) { + fprintf(fp, "\n"); + subtree = (LttvAttribute *)*(value.v_gobject); + saved_length = indent->len; + g_string_append(indent, " "); + print_tree(fp, indent, subtree); + g_string_truncate(indent, saved_length); + } + else fprintf(fp, "GOBJECT\n"); + break; + case LTTV_NONE: + break; + } + } +} + + +static void +print_stats(FILE *fp, LttvTracesetStats *tscs) +{ + int i, nb, saved_length; + + LttvTraceset *ts; + + LttvTraceStats *tcs; + + GString *indent; + + LttSystemDescription *desc; + + if(tscs->stats == NULL) return; + indent = g_string_new(""); + fprintf(fp, "Traceset statistics:\n\n"); + print_tree(fp, indent, tscs->stats); + + ts = tscs->parent.parent.ts; + nb = lttv_traceset_number(ts); + + for(i = 0 ; i < nb ; i++) { + tcs = (LttvTraceStats *)(LTTV_TRACESET_CONTEXT(tscs)->traces[i]); + desc = ltt_trace_system_description(tcs->parent.parent.t); + fprintf(fp, "Trace on system %s at time %d secs:\n", + ltt_trace_system_description_node_name(desc), + (ltt_trace_system_description_trace_start_time(desc)).tv_sec); + saved_length = indent->len; + g_string_append(indent, " "); + print_tree(fp, indent, tcs->stats); + g_string_truncate(indent, saved_length); + } + g_string_free(indent, TRUE); +} + + +/* Insert the hooks before and after each trace and tracefile, and for each + event. Print a global header. */ + +static FILE *a_file; + +static GString *a_string; + +static gboolean write_traceset_header(void *hook_data, void *call_data) +{ + LttvTracesetContext *tc = (LttvTracesetContext *)call_data; + + g_info("TextDump traceset header"); + + if(a_file_name == NULL) a_file = stdout; + else a_file = fopen(a_file_name, "w"); + + if(a_file == NULL) g_error("cannot open file %s", a_file_name); + + /* Print the trace set header */ + fprintf(a_file,"Trace set contains %d traces\n\n", + lttv_traceset_number(tc->ts)); + + return FALSE; +} + + +static gboolean write_traceset_footer(void *hook_data, void *call_data) +{ + LttvTracesetContext *tc = (LttvTracesetContext *)call_data; + + g_info("TextDump traceset footer"); + + fprintf(a_file,"End trace set\n\n"); + + if(LTTV_IS_TRACESET_STATS(tc)) { + print_stats(a_file, (LttvTracesetStats *)tc); + } + + if(a_file_name != NULL) fclose(a_file); + + return FALSE; +} + + +static gboolean write_trace_header(void *hook_data, void *call_data) +{ + LttvTraceContext *tc = (LttvTraceContext *)call_data; + + LttSystemDescription *system = ltt_trace_system_description(tc->t); + + fprintf(a_file," Trace from %s in %s\n%s\n\n", + ltt_trace_system_description_node_name(system), + ltt_trace_system_description_domain_name(system), + ltt_trace_system_description_description(system)); + return FALSE; +} + + +static int write_event_content(void *hook_data, void *call_data) +{ + LttvTracefileContext *tfc = (LttvTracefileContext *)call_data; + + LttvTracefileState *tfs = (LttvTracefileState *)call_data; + + LttEvent *e; + + e = tfc->e; + + lttv_event_to_string(e, tfc->tf, a_string, TRUE, a_field_names, tfs); + g_string_append_printf(a_string,"\n"); + + if(a_state) { + g_string_append_printf(a_string, " %s ", + g_quark_to_string(tfs->process->state->s)); + } + + fputs(a_string->str, a_file); + return FALSE; +} + + +G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv) +{ + LttvAttributeValue value; + + LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); + + g_info("Init textDump.c"); + + lttv_module_require(self, "libbatchAnalysis", argc, argv); + + a_string = g_string_new(""); + + a_file_name = NULL; + lttv_option_add("output", 'o', + "output file where the text is written", + "file name", + LTTV_OPT_STRING, &a_file_name, NULL, NULL); + + a_field_names = FALSE; + lttv_option_add("field_names", 'l', + "write the field names for each event", + "", + LTTV_OPT_NONE, &a_field_names, NULL, NULL); + + a_state = FALSE; + lttv_option_add("process_state", 's', + "write the pid and state for each event", + "", + LTTV_OPT_NONE, &a_state, NULL, NULL); + + a_cpu_stats = FALSE; + lttv_option_add("cpu_stats", 'c', + "write the per cpu statistics", + "", + LTTV_OPT_NONE, &a_cpu_stats, NULL, NULL); + + a_process_stats = FALSE; + lttv_option_add("process_stats", 'p', + "write the per process statistics", + "", + LTTV_OPT_NONE, &a_process_stats, NULL, NULL); + + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/before", + LTTV_POINTER, &value)); + g_assert((before_event = *(value.v_pointer)) != NULL); + lttv_hooks_add(before_event, write_event_content, NULL); + + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/before", + LTTV_POINTER, &value)); + g_assert((before_trace = *(value.v_pointer)) != NULL); + lttv_hooks_add(before_trace, write_trace_header, NULL); + + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/before", + LTTV_POINTER, &value)); + g_assert((before_traceset = *(value.v_pointer)) != NULL); + lttv_hooks_add(before_traceset, write_traceset_header, NULL); + + g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/after", + LTTV_POINTER, &value)); + g_assert((after_traceset = *(value.v_pointer)) != NULL); + lttv_hooks_add(after_traceset, write_traceset_footer, NULL); +} + + +G_MODULE_EXPORT void destroy() +{ + g_info("Destroy textDump"); + + lttv_option_remove("output"); + + lttv_option_remove("field_names"); + + lttv_option_remove("process_state"); + + lttv_option_remove("cpu_stats"); + + lttv_option_remove("process_stats"); + + g_string_free(a_string, TRUE); + + lttv_hooks_remove_data(before_event, write_event_content, NULL); + + lttv_hooks_remove_data(before_trace, write_trace_header, NULL); + + lttv_hooks_remove_data(before_trace, write_traceset_header, NULL); + + lttv_hooks_remove_data(before_trace, write_traceset_footer, NULL); +} + + + + diff --git a/ltt/branches/poly/lttv/option.c b/ltt/branches/poly/lttv/option.c deleted file mode 100644 index 590f9def..00000000 --- a/ltt/branches/poly/lttv/option.c +++ /dev/null @@ -1,264 +0,0 @@ - -#include -#include -#include - -#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) -#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) - -typedef struct _LttvOption { - char *long_name; - char char_name; - char *description; - char *arg_description; - LttvOptionType t; - gpointer p; - LttvOptionHook hook; - gpointer hook_data; -} LttvOption; - -GHashTable *options; - - -static void -list_options(gpointer key, gpointer value, gpointer user_data) -{ - g_ptr_array_add((GPtrArray *)user_data, value); -} - - -static void -free_option(LttvOption *option) -{ - g_free(option->long_name); - g_free(option->description); - g_free(option->arg_description); - g_free(option); -} - - -void lttv_option_init(int argc, char **argv) -{ - g_info("Init option.c"); - options = g_hash_table_new(g_str_hash, g_str_equal); -} - - -void lttv_option_destroy() -{ - LttvOption option; - - GPtrArray *list = g_ptr_array_new(); - - int i; - - g_info("Destroy option.c"); - g_hash_table_foreach(options, list_options, list); - g_hash_table_destroy(options); - - for(i = 0 ; i < list->len ; i++) { - free_option((LttvOption *)list->pdata[i]); - } - g_ptr_array_free(list, TRUE); -} - - -void lttv_option_add(const char *long_name, const char char_name, - const char *description, const char *arg_description, - const LttvOptionType t, void *p, - const LttvOptionHook h, void *hook_data) -{ - LttvOption *option; - - g_info("Add option %s", long_name); - if(g_hash_table_lookup(options, long_name) != NULL) { - g_warning("duplicate option"); - return; - } - - option = g_new(LttvOption, 1); - option->long_name = g_strdup(long_name); - option->char_name = char_name; - option->description = g_strdup(description); - option->arg_description = g_strdup(arg_description); - option->t = t; - option->p = p; - option->hook = h; - option->hook_data = hook_data; - g_hash_table_insert(options, option->long_name, option); -} - - -void -lttv_option_remove(const char *long_name) -{ - LttvOption *option = g_hash_table_lookup(options, long_name); - - g_info("Remove option %s", long_name); - if(option == NULL) { - g_warning("trying to remove unknown option %s", long_name); - return; - } - g_hash_table_remove(options, long_name); - free_option(option); -} - - -static int poptToLTT[] = { - POPT_ARG_NONE, POPT_ARG_STRING, POPT_ARG_INT, POPT_ARG_LONG -}; - -static struct poptOption endOption = { NULL, '\0', 0, NULL, 0}; - - -static void -build_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc, - int argc, char **argv) -{ - LttvOption *option; - - GPtrArray *list; - - struct poptOption *popts; - - poptContext c; - - guint i; - - list = g_ptr_array_new(); - - g_hash_table_foreach(options, list_options, list); - - /* Build a popt options array from our list */ - - popts = g_new(struct poptOption, list->len + 1); - - for(i = 0 ; i < list->len ; i++) { - option = (LttvOption *)list->pdata[i]; - popts[i].longName = option->long_name; - popts[i].shortName = option->char_name; - popts[i].descrip = option->description; - popts[i].argDescrip = option->arg_description; - popts[i].argInfo = poptToLTT[option->t]; - popts[i].arg = option->p; - popts[i].val = i + 1; - } - - /* Terminate the array for popt and create the context */ - - popts[list->len] = endOption; - c = poptGetContext(argv[0], argc, (const char**)argv, popts, 0); - - *plist = list; - *ppopts = popts; - *pc = c; -} - - -static void -destroy_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc) -{ - g_ptr_array_free(*plist, TRUE); *plist = NULL; - g_free(*ppopts); *ppopts = NULL; - poptFreeContext(*pc); -} - - -void lttv_option_parse(int argc, char **argv) -{ - GPtrArray *list; - - LttvOption *option; - - int i, rc, first_arg; - - struct poptOption *popts; - - poptContext c; - - i = 0; - - first_arg = 0; - - build_popts(&list, &popts, &c, argc, argv); - - /* Parse options while not end of options event */ - - while((rc = poptGetNextOpt(c)) != -1) { - - /* The option was recognized and the rc value returned is the argument - position in the array. Call the associated hook if present. */ - - if(rc > 0) { - option = (LttvOption *)(list->pdata[rc - 1]); - g_info("Option %s encountered", option->long_name); - if(option->hook != NULL) { - g_info("Option %s hook called", option->long_name); - option->hook(option->hook_data); - } - i++; - } - - else if(rc == POPT_ERROR_BADOPT && i != first_arg) { - g_info("Option %s not recognized, rescan options with new additions", - poptBadOption(c,0)); - - /* Perhaps this option is newly added, restart parsing */ - - destroy_popts(&list, &popts, &c); - build_popts(&list, &popts, &c, argc, argv); - - /* Get back to the same argument */ - - first_arg = i; - for(i = 0; i < first_arg; i++) { - rc = poptGetNextOpt(c); - option = (LttvOption *)(list->pdata[rc - 1]); - g_info("Option %s rescanned, skipped", option->long_name); - } - } - - else { - - /* The option has some error and it is not because this is a newly - added option not recognized. */ - - g_error("option %s: %s", poptBadOption(c,0), poptStrerror(rc)); - break; - } - - } - - destroy_popts(&list, &popts, &c); -} - -static void show_help(LttvOption *option) -{ - printf("--%s -%c argument: %s\n" , option->long_name, - option->char_name, - option->arg_description); - printf(" %s\n" , option->description); - -} - -void lttv_option_show_help(void) -{ - LttvOption option; - - GPtrArray *list = g_ptr_array_new(); - - int i; - - g_hash_table_foreach(options, list_options, list); - - printf("Built-in commands available:\n"); - printf("\n"); - - for(i = 0 ; i < list->len ; i++) { - show_help((LttvOption *)list->pdata[i]); - } - g_ptr_array_free(list, TRUE); - - -} - diff --git a/ltt/branches/poly/lttv/processTrace.c b/ltt/branches/poly/lttv/processTrace.c deleted file mode 100644 index 4a290dd0..00000000 --- a/ltt/branches/poly/lttv/processTrace.c +++ /dev/null @@ -1,812 +0,0 @@ - -#include -#include -#include -#include -#include - -void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts) -{ - LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts); -} - - -void lttv_context_fini(LttvTracesetContext *self) -{ - LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self); -} - - -LttvTracesetContext * -lttv_context_new_traceset_context(LttvTracesetContext *self) -{ - return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self); -} - - - - -LttvTraceContext * -lttv_context_new_trace_context(LttvTracesetContext *self) -{ - return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self); -} - - -LttvTracefileContext * -lttv_context_new_tracefile_context(LttvTracesetContext *self) -{ - return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self); -} - -/**************************************************************************** - * lttv_traceset_context_compute_time_span - * - * Keep the Time_Span is sync with on the fly addition and removal of traces - * in a trace set. It must be called each time a trace is added/removed from - * the traceset. It could be more efficient to call it only once a bunch - * of traces are loaded, but the calculation is not long, so it's not - * critical. - * - * Author : Xang Xiu Yang - * Imported from gtkTraceSet.c by Mathieu Desnoyers - ***************************************************************************/ -static void lttv_traceset_context_compute_time_span( - LttvTracesetContext *self, - TimeInterval *Time_Span) -{ - LttvTraceset * traceset = self->ts; - int numTraces = lttv_traceset_number(traceset); - int i; - LttTime s, e; - LttvTraceContext *tc; - LttTrace * trace; - - for(i=0; itraces[i]; - trace = tc->t; - - ltt_trace_time_span_get(trace, &s, &e); - - if(i==0){ - Time_Span->startTime = s; - Time_Span->endTime = e; - }else{ - if(s.tv_sec < Time_Span->startTime.tv_sec || - (s.tv_sec == Time_Span->startTime.tv_sec - && s.tv_nsec < Time_Span->startTime.tv_nsec)) - Time_Span->startTime = s; - if(e.tv_sec > Time_Span->endTime.tv_sec || - (e.tv_sec == Time_Span->endTime.tv_sec && - e.tv_nsec > Time_Span->endTime.tv_nsec)) - Time_Span->endTime = e; - } - } -} - - -static void -init(LttvTracesetContext *self, LttvTraceset *ts) -{ - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTracefileContext *tfc; - - LttTime null_time = {0, 0}; - - nb_trace = lttv_traceset_number(ts); - self->ts = ts; - self->traces = g_new(LttvTraceContext *, nb_trace); - self->before = lttv_hooks_new(); - self->after = lttv_hooks_new(); - self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - self->ts_a = lttv_traceset_attribute(ts); - for(i = 0 ; i < nb_trace ; i++) { - tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self); - self->traces[i] = tc; - - tc->ts_context = self; - tc->index = i; - tc->vt = lttv_traceset_get(ts, i); - tc->t = lttv_trace(tc->vt); - tc->check = lttv_hooks_new(); - tc->before = lttv_hooks_new(); - tc->after = lttv_hooks_new(); - tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - tc->t_a = lttv_trace_attribute(tc->vt); - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - tc->control_tracefiles = g_new(LttvTracefileContext *, nb_control); - tc->per_cpu_tracefiles = g_new(LttvTracefileContext *, nb_per_cpu); - - for(j = 0 ; j < nb_tracefile ; j++) { - tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self); - if(j < nb_control) { - tc->control_tracefiles[j] = tfc; - tfc->control = TRUE; - tfc->index = j; - tfc->tf = ltt_trace_control_tracefile_get(tc->t, j); - } - else { - tc->per_cpu_tracefiles[j - nb_control] = tfc; - tfc->control = FALSE; - tfc->index = j - nb_control; - tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control); - } - tfc->t_context = tc; - tfc->check = lttv_hooks_new(); - tfc->before = lttv_hooks_new(); - tfc->after = lttv_hooks_new(); - tfc->check_event = lttv_hooks_new(); - tfc->before_event = lttv_hooks_new(); - tfc->before_event_by_id = lttv_hooks_by_id_new(); - tfc->after_event = lttv_hooks_new(); - tfc->after_event_by_id = lttv_hooks_by_id_new(); - tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - } - } - lttv_process_traceset_seek_time(self, null_time); - /*CHECK why dynamically allocate the time span... and the casing is wroNg*/ - self->Time_Span = g_new(TimeInterval,1); - lttv_traceset_context_compute_time_span(self, self->Time_Span); -} - - -void fini(LttvTracesetContext *self) -{ - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTracefileContext *tfc; - - LttvTraceset *ts = self->ts; - - g_free(self->Time_Span); - - lttv_hooks_destroy(self->before); - lttv_hooks_destroy(self->after); - //FIXME : segfault - g_object_unref(self->a); - - nb_trace = lttv_traceset_number(ts); - - for(i = 0 ; i < nb_trace ; i++) { - tc = self->traces[i]; - - lttv_hooks_destroy(tc->check); - lttv_hooks_destroy(tc->before); - lttv_hooks_destroy(tc->after); - g_object_unref(tc->a); - - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) tfc = tc->control_tracefiles[j]; - else tfc = tc->per_cpu_tracefiles[j - nb_control]; - - lttv_hooks_destroy(tfc->check); - lttv_hooks_destroy(tfc->before); - lttv_hooks_destroy(tfc->after); - lttv_hooks_destroy(tfc->check_event); - lttv_hooks_destroy(tfc->before_event); - lttv_hooks_by_id_destroy(tfc->before_event_by_id); - lttv_hooks_destroy(tfc->after_event); - lttv_hooks_by_id_destroy(tfc->after_event_by_id); - g_object_unref(tfc->a); - g_object_unref(tfc); - } - g_free(tc->control_tracefiles); - g_free(tc->per_cpu_tracefiles); - g_object_unref(tc); - } - g_free(self->traces); -} - - -void lttv_traceset_context_add_hooks(LttvTracesetContext *self, - LttvHooks *before_traceset, - LttvHooks *after_traceset, - LttvHooks *check_trace, - LttvHooks *before_trace, - LttvHooks *after_trace, - LttvHooks *check_tracefile, - LttvHooks *before_tracefile, - LttvHooks *after_tracefile, - LttvHooks *check_event, - LttvHooks *before_event, - LttvHooks *after_event) -{ - LttvTraceset *ts = self->ts; - - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTracefileContext *tfc; - - void *hook_data; - - lttv_hooks_add_list(self->before, before_traceset); - lttv_hooks_add_list(self->after, after_traceset); - nb_trace = lttv_traceset_number(ts); - - for(i = 0 ; i < nb_trace ; i++) { - tc = self->traces[i]; - lttv_hooks_add_list(tc->check, check_trace); - lttv_hooks_add_list(tc->before, before_trace); - lttv_hooks_add_list(tc->after, after_trace); - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfc = tc->control_tracefiles[j]; - } - else { - tfc = tc->per_cpu_tracefiles[j-nb_control]; - } - lttv_hooks_add_list(tfc->check, check_tracefile); - lttv_hooks_add_list(tfc->before, before_tracefile); - lttv_hooks_add_list(tfc->after, after_tracefile); - lttv_hooks_add_list(tfc->check_event, check_event); - lttv_hooks_add_list(tfc->before_event, before_event); - lttv_hooks_add_list(tfc->after_event, after_event); - } - } -} - - -void lttv_traceset_context_remove_hooks(LttvTracesetContext *self, - LttvHooks *before_traceset, - LttvHooks *after_traceset, - LttvHooks *check_trace, - LttvHooks *before_trace, - LttvHooks *after_trace, - LttvHooks *check_tracefile, - LttvHooks *before_tracefile, - LttvHooks *after_tracefile, - LttvHooks *check_event, - LttvHooks *before_event, - LttvHooks *after_event) -{ - LttvTraceset *ts = self->ts; - - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTracefileContext *tfc; - - void *hook_data; - - lttv_hooks_remove_list(self->before, before_traceset); - lttv_hooks_remove_list(self->after, after_traceset); - nb_trace = lttv_traceset_number(ts); - - for(i = 0 ; i < nb_trace ; i++) { - tc = self->traces[i]; - lttv_hooks_remove_list(tc->check, check_trace); - lttv_hooks_remove_list(tc->before, before_trace); - lttv_hooks_remove_list(tc->after, after_trace); - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfc = tc->control_tracefiles[j]; - } - else { - tfc = tc->per_cpu_tracefiles[j-nb_control]; - } - lttv_hooks_remove_list(tfc->check, check_tracefile); - lttv_hooks_remove_list(tfc->before, before_tracefile); - lttv_hooks_remove_list(tfc->after, after_tracefile); - lttv_hooks_remove_list(tfc->check_event, check_event); - lttv_hooks_remove_list(tfc->before_event, before_event); - lttv_hooks_remove_list(tfc->after_event, after_event); - } - } -} - -void lttv_trace_context_add_hooks(LttvTraceContext *tc, - LttvHooks *check_trace, - LttvHooks *before_trace, - LttvHooks *after_trace) -{ - lttv_hooks_add_list(tc->check, check_trace); - lttv_hooks_add_list(tc->before, before_trace); - lttv_hooks_add_list(tc->after, after_trace); -} - -void lttv_trace_context_remove_hooks(LttvTraceContext *tc, - LttvHooks *check_trace, - LttvHooks *before_trace, - LttvHooks *after_trace) -{ - lttv_hooks_remove_list(tc->check, check_trace); - lttv_hooks_remove_list(tc->before, before_trace); - lttv_hooks_remove_list(tc->after, after_trace); -} - -void lttv_tracefile_context_add_hooks(LttvTracefileContext *tfc, - LttvHooks *check_tracefile, - LttvHooks *before_tracefile, - LttvHooks *after_tracefile, - LttvHooks *check_event, - LttvHooks *before_event, - LttvHooks *after_event) -{ - lttv_hooks_add_list(tfc->check, check_tracefile); - lttv_hooks_add_list(tfc->before, before_tracefile); - lttv_hooks_add_list(tfc->after, after_tracefile); - lttv_hooks_add_list(tfc->check_event, check_event); - lttv_hooks_add_list(tfc->before_event, before_event); - lttv_hooks_add_list(tfc->after_event, after_event); -} - -void lttv_tracefile_context_remove_hooks(LttvTracefileContext *tfc, - LttvHooks *check_tracefile, - LttvHooks *before_tracefile, - LttvHooks *after_tracefile, - LttvHooks *check_event, - LttvHooks *before_event, - LttvHooks *after_event) -{ - lttv_hooks_remove_list(tfc->check, check_tracefile); - lttv_hooks_remove_list(tfc->before, before_tracefile); - lttv_hooks_remove_list(tfc->after, after_tracefile); - lttv_hooks_remove_list(tfc->check_event, check_event); - lttv_hooks_remove_list(tfc->before_event, before_event); - lttv_hooks_remove_list(tfc->after_event, after_event); -} - -void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc, - unsigned i, - LttvHooks *before_event_by_id, - LttvHooks *after_event_by_id) -{ - LttvHooks * h; - h = lttv_hooks_by_id_find(tfc->before_event_by_id, i); - lttv_hooks_add_list(h, before_event_by_id); - h = lttv_hooks_by_id_find(tfc->after_event_by_id, i); - lttv_hooks_add_list(h, after_event_by_id); -} - -void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc, - unsigned i) -{ - lttv_hooks_by_id_remove(tfc->before_event_by_id, i); - lttv_hooks_by_id_remove(tfc->after_event_by_id, i); -} - -static LttvTracesetContext * -new_traceset_context(LttvTracesetContext *self) -{ - return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL); -} - - -static LttvTraceContext * -new_trace_context(LttvTracesetContext *self) -{ - return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL); -} - - -static LttvTracefileContext * -new_tracefile_context(LttvTracesetContext *self) -{ - return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL); -} - - -static void -traceset_context_instance_init (GTypeInstance *instance, gpointer g_class) -{ - /* Be careful of anything which would not work well with shallow copies */ -} - - -static void -traceset_context_finalize (LttvTracesetContext *self) -{ - G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE))) - ->finalize(G_OBJECT(self)); -} - - -static void -traceset_context_class_init (LttvTracesetContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize; - klass->init = init; - klass->fini = fini; - klass->new_traceset_context = new_traceset_context; - klass->new_trace_context = new_trace_context; - klass->new_tracefile_context = new_tracefile_context; -} - - -GType -lttv_traceset_context_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracesetContextClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) traceset_context_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracesetContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) traceset_context_instance_init /* instance_init */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType", - &info, 0); - } - return type; -} - - -static void -trace_context_instance_init (GTypeInstance *instance, gpointer g_class) -{ - /* Be careful of anything which would not work well with shallow copies */ -} - - -static void -trace_context_finalize (LttvTraceContext *self) -{ - G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))-> - finalize(G_OBJECT(self)); -} - - -static void -trace_context_class_init (LttvTraceContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize; -} - - -GType -lttv_trace_context_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTraceContextClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) trace_context_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTraceContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) trace_context_instance_init /* instance_init */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType", - &info, 0); - } - return type; -} - - -static void -tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class) -{ - /* Be careful of anything which would not work well with shallow copies */ -} - - -static void -tracefile_context_finalize (LttvTracefileContext *self) -{ - G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE))) - ->finalize(G_OBJECT(self)); -} - - -static void -tracefile_context_class_init (LttvTracefileContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize; -} - - -GType -lttv_tracefile_context_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracefileContextClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) tracefile_context_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracefileContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) tracefile_context_instance_init /* instance_init */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType", - &info, 0); - } - return type; -} - - -gint compare_tracefile(gconstpointer a, gconstpointer b) -{ - return ltt_time_compare(*((LttTime *)a), *((LttTime *)b)); -} - - -gboolean get_first(gpointer key, gpointer value, gpointer user_data) { - *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value; - return TRUE; -} - - -void lttv_process_traceset(LttvTracesetContext *self, LttTime end, - unsigned maxNumEvents) -{ - GPtrArray *traces = g_ptr_array_new(); - - GPtrArray *tracefiles = g_ptr_array_new(); - - GTree *pqueue = g_tree_new(compare_tracefile); - - guint i, j, nbi, nbj, id, nb_control, nb_cpu; - - LttTrace *trace; - - LttvTraceContext *tc; - - LttTracefile *tracefile; - - LttvTracefileContext *tfc; - - LttEvent *event; - - unsigned count = 0; - - LttTime previous_timestamp = {0, 0}; - - /* Call all before_traceset, before_trace, and before_tracefile hooks. - For all qualifying tracefiles, seek to the start time, create a context, - read one event and insert in the pqueue based on the event time. */ - - lttv_hooks_call(self->before, self); - nbi = lttv_traceset_number(self->ts); - - for(i = 0 ; i < nbi ; i++) { - tc = self->traces[i]; - trace = tc->t; - - if(!lttv_hooks_call_check(tc->check, tc)) { - g_ptr_array_add(traces, tc); - lttv_hooks_call(tc->before, tc); - nb_control = ltt_trace_control_tracefile_number(trace); - nb_cpu = ltt_trace_per_cpu_tracefile_number(trace); - nbj = nb_control + nb_cpu; - - for(j = 0 ; j < nbj ; j++) { - if(j < nb_control) { - tfc = tc->control_tracefiles[j]; - } - else { - tfc = tc->per_cpu_tracefiles[j - nb_control]; - } - - tracefile = tfc->tf; - - if(!lttv_hooks_call_check(tfc->check, tfc)) { - g_ptr_array_add(tracefiles, tfc); - lttv_hooks_call(tfc->before, tfc); - - if(tfc->e != NULL) { - if(tfc->timestamp.tv_sec < end.tv_sec || - (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec)){ - g_tree_insert(pqueue, &(tfc->timestamp), tfc); - } - } - } - } - } - } - - /* Get the next event from the pqueue, call its hooks, - reinsert in the pqueue the following event from the same tracefile - unless the tracefile is finished or the event is later than the - start time. */ - - while(TRUE) { - tfc = NULL; - g_tree_foreach(pqueue, get_first, &tfc); - if(tfc == NULL) break; - - /* Have we reached the maximum number of events specified? However, - continue for all the events with the same time stamp (CHECK?). Then, - empty the queue and break from the loop. */ - - count++; - if(count > maxNumEvents){ - if(tfc->timestamp.tv_sec == previous_timestamp.tv_sec && - tfc->timestamp.tv_nsec == previous_timestamp.tv_nsec) { - count--; - }else{ - while(TRUE){ - tfc = NULL; - g_tree_foreach(pqueue, get_first, &tfc); - if(tfc == NULL) break; - g_tree_remove(pqueue, &(tfc->timestamp)); - } - break; - } - } - previous_timestamp = tfc->timestamp; - - - /* Get the tracefile with an event for the smallest time found. If two - or more tracefiles have events for the same time, hope that lookup - and remove are consistent. */ - - tfc = g_tree_lookup(pqueue, &(tfc->timestamp)); - g_tree_remove(pqueue, &(tfc->timestamp)); - - if(!lttv_hooks_call(tfc->check_event, tfc)) { - id = ltt_event_eventtype_id(tfc->e); - lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc); - lttv_hooks_call(tfc->before_event, tfc); - lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc); - lttv_hooks_call(tfc->after_event, tfc); - } - - event = ltt_tracefile_read(tfc->tf); - if(event != NULL) { - tfc->e = event; - tfc->timestamp = ltt_event_time(event); - if(tfc->timestamp.tv_sec < end.tv_sec || - (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec)) - g_tree_insert(pqueue, &(tfc->timestamp), tfc); - } - } - - /* Call all the after_tracefile, after_trace and after_traceset hooks. */ - - for(i = 0, j = 0 ; i < traces->len ; i++) { - tc = traces->pdata[i]; - while(j < tracefiles->len) { - tfc = tracefiles->pdata[j]; - - if(tfc->t_context == tc) { - lttv_hooks_call(tfc->after, tfc); - j++; - } - else break; - } - lttv_hooks_call(tc->after, tc); - } - - g_assert(j == tracefiles->len); - lttv_hooks_call(self->after, self); - - /* Free the traces, tracefiles and pqueue */ - - g_ptr_array_free(tracefiles, TRUE); - g_ptr_array_free(traces, TRUE); - g_tree_destroy(pqueue); -} - - -void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start) -{ - guint i, nb_control, nb_per_cpu, nb_tracefile; - - LttvTracefileContext *tfc; - - LttEvent *event; - - nb_control = ltt_trace_control_tracefile_number(self->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->t); - nb_tracefile = nb_control + nb_per_cpu; - for(i = 0 ; i < nb_tracefile ; i++) { - if(i < nb_control) tfc = self->control_tracefiles[i]; - else tfc = self->per_cpu_tracefiles[i - nb_control]; - - ltt_tracefile_seek_time(tfc->tf, start); - event = ltt_tracefile_read(tfc->tf); - tfc->e = event; - if(event != NULL) tfc->timestamp = ltt_event_time(event); - } -} - - -void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start) -{ - guint i, nb_trace; - - LttvTraceContext *tc; - - nb_trace = lttv_traceset_number(self->ts); - for(i = 0 ; i < nb_trace ; i++) { - tc = self->traces[i]; - lttv_process_trace_seek_time(tc, start); - } -} - - -static LttField * -find_field(LttEventType *et, const char *field) -{ - LttType *t; - - LttField *f; - - guint i, nb; - - char *name; - - if(field == NULL) return NULL; - - f = ltt_eventtype_field(et); - t = ltt_eventtype_type(et); - g_assert(ltt_type_class(t) == LTT_STRUCT); - nb = ltt_type_member_number(t); - for(i = 0 ; i < nb ; i++) { - ltt_type_member_type(t, i, &name); - if(strcmp(name, field) == 0) break; - } - g_assert(i < nb); - return ltt_field_member(f, i); -} - - -void -lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type, - char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th) -{ - LttFacility *f; - - LttEventType *et; - - guint nb, pos, i; - - char *name; - - nb = ltt_trace_facility_find(t, facility, &pos); - if(nb < 1) g_error("No %s facility", facility); - f = ltt_trace_facility_get(t, pos); - et = ltt_facility_eventtype_get_by_name(f, event_type); - if(et == NULL) g_error("Event %s does not exist", event_type); - - th->h = h; - th->id = ltt_eventtype_id(et); - th->f1 = find_field(et, field1); - th->f2 = find_field(et, field2); - th->f3 = find_field(et, field3); -} - - diff --git a/ltt/branches/poly/lttv/state.c b/ltt/branches/poly/lttv/state.c deleted file mode 100644 index dbdb11ce..00000000 --- a/ltt/branches/poly/lttv/state.c +++ /dev/null @@ -1,1198 +0,0 @@ - -#include -#include -#include -#include -#include - -LttvExecutionMode - LTTV_STATE_MODE_UNKNOWN, - LTTV_STATE_USER_MODE, - LTTV_STATE_SYSCALL, - LTTV_STATE_TRAP, - LTTV_STATE_IRQ; - -LttvExecutionSubmode - LTTV_STATE_SUBMODE_UNKNOWN, - LTTV_STATE_SUBMODE_NONE; - -LttvProcessStatus - LTTV_STATE_UNNAMED, - LTTV_STATE_WAIT_FORK, - LTTV_STATE_WAIT_CPU, - LTTV_STATE_EXIT, - LTTV_STATE_WAIT, - LTTV_STATE_RUN; - -static GQuark - LTTV_STATE_TRACEFILES, - LTTV_STATE_PROCESSES, - LTTV_STATE_PROCESS, - LTTV_STATE_EVENT, - LTTV_STATE_SAVED_STATES, - LTTV_STATE_TIME, - LTTV_STATE_HOOKS; - - -static void fill_name_tables(LttvTraceState *tcs); - -static void free_name_tables(LttvTraceState *tcs); - -static void lttv_state_free_process_table(GHashTable *processes); - -static LttvProcessState *create_process(LttvTracefileState *tfs, - LttvProcessState *parent, guint pid); - -void lttv_state_save(LttvTraceState *self, LttvAttribute *container) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container); -} - - -void lttv_state_restore(LttvTraceState *self, LttvAttribute *container) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); -} - - -void lttv_state_saved_state_free(LttvTraceState *self, - LttvAttribute *container) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); -} - - -static void -restore_init_state(LttvTraceState *self) -{ - guint i, nb_control, nb_per_cpu, nb_tracefile; - - LttvTracefileState *tfcs; - - LttTime null_time = {0,0}; - - if(self->processes != NULL) lttv_state_free_process_table(self->processes); - self->processes = g_hash_table_new(g_direct_hash, g_direct_equal); - self->nb_event = 0; - - nb_control = ltt_trace_control_tracefile_number(self->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(i = 0 ; i < nb_tracefile ; i++) { - if(i < nb_control) { - tfcs = LTTV_TRACEFILE_STATE(self->parent.control_tracefiles[i]); - } - else { - tfcs = LTTV_TRACEFILE_STATE(self->parent.per_cpu_tracefiles[i - nb_control]); - } - - tfcs->parent.timestamp = null_time; - tfcs->saved_position = 0; - tfcs->process = create_process(tfcs, NULL,0); - } -} - - -static void -init(LttvTracesetState *self, LttvTraceset *ts) -{ - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTraceState *tcs; - - LttvTracefileState *tfcs; - - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> - init((LttvTracesetContext *)self, ts); - - nb_trace = lttv_traceset_number(ts); - for(i = 0 ; i < nb_trace ; i++) { - tc = self->parent.traces[i]; - tcs = (LttvTraceState *)tc; - tcs->save_interval = 100000; - fill_name_tables(tcs); - - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfcs = LTTV_TRACEFILE_STATE(tc->control_tracefiles[j]); - } - else { - tfcs = LTTV_TRACEFILE_STATE(tc->per_cpu_tracefiles[j - nb_control]); - } - tfcs->cpu_name= g_quark_from_string(ltt_tracefile_name(tfcs->parent.tf)); - } - tcs->processes = NULL; - restore_init_state(tcs); - } -} - - -static void -fini(LttvTracesetState *self) -{ - guint i, j, nb_trace, nb_tracefile; - - LttvTraceState *tcs; - - LttvTracefileState *tfcs; - - nb_trace = lttv_traceset_number(LTTV_TRACESET_CONTEXT(self)->ts); - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceState *)(LTTV_TRACESET_CONTEXT(self)->traces[i]); - lttv_state_free_process_table(tcs->processes); - tcs->processes = NULL; - free_name_tables(tcs); - } - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> - fini((LttvTracesetContext *)self); -} - - -static LttvTracesetContext * -new_traceset_context(LttvTracesetContext *self) -{ - return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE, NULL)); -} - - -static LttvTraceContext * -new_trace_context(LttvTracesetContext *self) -{ - return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE, NULL)); -} - - -static LttvTracefileContext * -new_tracefile_context(LttvTracesetContext *self) -{ - return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE, NULL)); -} - - -static void copy_process_state(gpointer key, gpointer value,gpointer user_data) -{ - LttvProcessState *process, *new_process; - - GHashTable *new_processes = (GHashTable *)user_data; - - guint i; - - process = (LttvProcessState *)value; - new_process = g_new(LttvProcessState, 1); - *new_process = *process; - new_process->execution_stack = g_array_new(FALSE, FALSE, - sizeof(LttvExecutionState)); - g_array_set_size(new_process->execution_stack,process->execution_stack->len); - for(i = 0 ; i < process->execution_stack->len; i++) { - g_array_index(new_process->execution_stack, LttvExecutionState, i) = - g_array_index(process->execution_stack, LttvExecutionState, i); - } - new_process->state = &g_array_index(new_process->execution_stack, - LttvExecutionState, new_process->execution_stack->len - 1); - g_hash_table_insert(new_processes, GUINT_TO_POINTER(new_process->pid), - new_process); -} - - -static GHashTable *lttv_state_copy_process_table(GHashTable *processes) -{ - GHashTable *new_processes = g_hash_table_new(g_direct_hash, g_direct_equal); - - g_hash_table_foreach(processes, copy_process_state, new_processes); - return new_processes; -} - - -/* The saved state for each trace contains a member "processes", which - stores a copy of the process table, and a member "tracefiles" with - one entry per tracefile. Each tracefile has a "process" member pointing - to the current process and a "position" member storing the tracefile - position (needed to seek to the current "next" event. */ - -static void state_save(LttvTraceState *self, LttvAttribute *container) -{ - guint i, nb_control, nb_per_cpu, nb_tracefile; - - LttvTracefileState *tfcs; - - LttvAttribute *tracefiles_tree, *tracefile_tree; - - LttvAttributeType type; - - LttvAttributeValue value; - - LttvAttributeName name; - - LttEventPosition *ep; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - - value = lttv_attribute_add(container, LTTV_STATE_PROCESSES, - LTTV_POINTER); - *(value.v_pointer) = lttv_state_copy_process_table(self->processes); - - nb_control = ltt_trace_control_tracefile_number(self->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - - for(i = 0 ; i < nb_tracefile ; i++) { - if(i < nb_control) - tfcs = (LttvTracefileState *)self->parent.control_tracefiles[i]; - else tfcs = (LttvTracefileState *) - self->parent.per_cpu_tracefiles[i - nb_control]; - - tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - value = lttv_attribute_add(tracefiles_tree, i, - LTTV_GOBJECT); - *(value.v_gobject) = (GObject *)tracefile_tree; - value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS, - LTTV_UINT); - *(value.v_uint) = tfcs->process->pid; - value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT, - LTTV_POINTER); - if(tfcs->parent.e == NULL) *(value.v_pointer) = NULL; - else { - ep = ltt_event_position_new(); - ltt_event_position(tfcs->parent.e, ep); - *(value.v_pointer) = ep; - } - } -} - - -static void state_restore(LttvTraceState *self, LttvAttribute *container) -{ - guint i, nb_control, nb_per_cpu, nb_tracefile; - - LttvTracefileState *tfcs; - - LttvAttribute *tracefiles_tree, *tracefile_tree; - - LttvAttributeType type; - - LttvAttributeValue value; - - LttvAttributeName name; - - LttEventPosition *ep; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - - type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, - &value); - g_assert(type == LTTV_POINTER); - lttv_state_free_process_table(self->processes); - self->processes = lttv_state_copy_process_table(*(value.v_pointer)); - - nb_control = ltt_trace_control_tracefile_number(self->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - - for(i = 0 ; i < nb_tracefile ; i++) { - if(i < nb_control) tfcs = (LttvTracefileState *) - self->parent.control_tracefiles[i]; - else tfcs = (LttvTracefileState *) - self->parent.per_cpu_tracefiles[i - nb_control]; - - type = lttv_attribute_get(tracefiles_tree, i, &name, &value); - g_assert(type == LTTV_GOBJECT); - tracefile_tree = *((LttvAttribute **)(value.v_gobject)); - - type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_PROCESS, - &value); - g_assert(type == LTTV_UINT); - tfcs->process = lttv_state_find_process(tfcs, *(value.v_uint)); - type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, - &value); - g_assert(type == LTTV_POINTER); - if(*(value.v_pointer) == NULL) tfcs->parent.e = NULL; - else { - ep = *(value.v_pointer); - ltt_tracefile_seek_position(tfcs->parent.tf, ep); - tfcs->parent.e = ltt_tracefile_read(tfcs->parent.tf); - tfcs->parent.timestamp = ltt_event_time(tfcs->parent.e); - } - } -} - - -static void state_saved_free(LttvTraceState *self, LttvAttribute *container) -{ - guint i, nb_control, nb_per_cpu, nb_tracefile; - - LttvTracefileState *tfcs; - - LttvAttribute *tracefiles_tree, *tracefile_tree; - - LttvAttributeType type; - - LttvAttributeValue value; - - LttvAttributeName name; - - LttEventPosition *ep; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES); - - type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, - &value); - g_assert(type == LTTV_POINTER); - lttv_state_free_process_table(*(value.v_pointer)); - *(value.v_pointer) = NULL; - lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES); - - nb_control = ltt_trace_control_tracefile_number(self->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - - for(i = 0 ; i < nb_tracefile ; i++) { - if(i < nb_control) tfcs = (LttvTracefileState *) - self->parent.control_tracefiles[i]; - else tfcs = (LttvTracefileState *) - self->parent.per_cpu_tracefiles[i - nb_control]; - - type = lttv_attribute_get(tracefiles_tree, i, &name, &value); - g_assert(type == LTTV_GOBJECT); - tracefile_tree = *((LttvAttribute **)(value.v_gobject)); - - type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, - &value); - g_assert(type == LTTV_POINTER); - if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer)); - } - lttv_attribute_recursive_free(tracefiles_tree); -} - - -static void -fill_name_tables(LttvTraceState *tcs) -{ - int i, nb; - - char *f_name, *e_name; - - LttvTraceHook h; - - LttEventType *et; - - LttType *t; - - GString *fe_name = g_string_new(""); - - nb = ltt_trace_eventtype_number(tcs->parent.t); - tcs->eventtype_names = g_new(GQuark, nb); - for(i = 0 ; i < nb ; i++) { - et = ltt_trace_eventtype_get(tcs->parent.t, i); - e_name = ltt_eventtype_name(et); - f_name = ltt_facility_name(ltt_eventtype_facility(et)); - g_string_printf(fe_name, "%s.%s", f_name, e_name); - tcs->eventtype_names[i] = g_quark_from_string(fe_name->str); - } - - lttv_trace_find_hook(tcs->parent.t, "core", "syscall_entry", - "syscall_id", NULL, NULL, NULL, &h); - t = ltt_field_type(h.f1); - nb = ltt_type_element_number(t); - - /* CHECK syscalls should be an emun but currently are not! - tcs->syscall_names = g_new(GQuark, nb); - - for(i = 0 ; i < nb ; i++) { - tcs->syscall_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); - } - */ - - tcs->syscall_names = g_new(GQuark, 256); - for(i = 0 ; i < 256 ; i++) { - g_string_printf(fe_name, "syscall %d", i); - tcs->syscall_names[i] = g_quark_from_string(fe_name->str); - } - - lttv_trace_find_hook(tcs->parent.t, "core", "trap_entry", - "trap_id", NULL, NULL, NULL, &h); - t = ltt_field_type(h.f1); - nb = ltt_type_element_number(t); - - /* - tcs->trap_names = g_new(GQuark, nb); - for(i = 0 ; i < nb ; i++) { - tcs->trap_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); - } - */ - - tcs->trap_names = g_new(GQuark, 256); - for(i = 0 ; i < 256 ; i++) { - g_string_printf(fe_name, "trap %d", i); - tcs->trap_names[i] = g_quark_from_string(fe_name->str); - } - - lttv_trace_find_hook(tcs->parent.t, "core", "irq_entry", - "irq_id", NULL, NULL, NULL, &h); - t = ltt_field_type(h.f1); - nb = ltt_type_element_number(t); - - /* - tcs->irq_names = g_new(GQuark, nb); - for(i = 0 ; i < nb ; i++) { - tcs->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); - } - */ - - tcs->irq_names = g_new(GQuark, 256); - for(i = 0 ; i < 256 ; i++) { - g_string_printf(fe_name, "irq %d", i); - tcs->irq_names[i] = g_quark_from_string(fe_name->str); - } - - g_string_free(fe_name, TRUE); -} - - -static void -free_name_tables(LttvTraceState *tcs) -{ - g_free(tcs->eventtype_names); - g_free(tcs->syscall_names); - g_free(tcs->trap_names); - g_free(tcs->irq_names); -} - - -static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, - guint state_id) -{ - LttvExecutionState *es; - - LttvProcessState *process = tfs->process; - - guint depth = process->execution_stack->len; - - g_array_set_size(process->execution_stack, depth + 1); - es = &g_array_index(process->execution_stack, LttvExecutionState, depth); - es->t = t; - es->n = state_id; - es->entry = es->change = tfs->parent.timestamp; - es->s = process->state->s; - process->state = es; -} - - -static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) -{ - LttvProcessState *process = tfs->process; - - guint depth = process->execution_stack->len - 1; - - if(process->state->t != t){ - g_warning("Different execution mode type (%d.%09d): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); - g_warning("process state has %s when pop_int is %s\n", - g_quark_to_string(process->state->t), - g_quark_to_string(t)); - g_warning("{ %u, %u, %s, %s }\n", - process->pid, - process->ppid, - g_quark_to_string(process->name), - g_quark_to_string(process->state->s)); - return; - } - - if(depth == 0){ - g_warning("Trying to pop last state on stack (%d.%09d): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); - return; - } - - g_array_remove_index(process->execution_stack, depth); - depth--; - process->state = &g_array_index(process->execution_stack, LttvExecutionState, - depth); - process->state->change = tfs->parent.timestamp; -} - - -static LttvProcessState *create_process(LttvTracefileState *tfs, - LttvProcessState *parent, guint pid) -{ - LttvProcessState *process = g_new(LttvProcessState, 1); - - LttvExecutionState *es; - - LttvTraceContext *tc; - - LttvTraceState *tcs; - - char buffer[128]; - - tcs = (LttvTraceState *)tc = tfs->parent.t_context; - - g_hash_table_insert(tcs->processes, GUINT_TO_POINTER(pid), process); - process->pid = pid; - - if(parent) { - process->ppid = parent->pid; - process->name = parent->name; - } - else { - process->ppid = 0; - process->name = LTTV_STATE_UNNAMED; - } - - process->creation_time = tfs->parent.timestamp; - sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec, - process->creation_time.tv_nsec); - process->pid_time = g_quark_from_string(buffer); - process->execution_stack = g_array_new(FALSE, FALSE, - sizeof(LttvExecutionState)); - g_array_set_size(process->execution_stack, 1); - es = process->state = &g_array_index(process->execution_stack, - LttvExecutionState, 0); - es->t = LTTV_STATE_USER_MODE; - es->n = LTTV_STATE_SUBMODE_NONE; - es->entry = tfs->parent.timestamp; - es->change = tfs->parent.timestamp; - es->s = LTTV_STATE_WAIT_FORK; - - return process; -} - - -LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs, - guint pid) -{ - LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context; - LttvProcessState *process = g_hash_table_lookup(ts->processes, - GUINT_TO_POINTER(pid)); - if(process == NULL) process = create_process(tfs, NULL, pid); - return process; -} - - -static void exit_process(LttvTracefileState *tfs, LttvProcessState *process) -{ - LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context); - - g_hash_table_remove(ts->processes, GUINT_TO_POINTER(process->pid)); - g_array_free(process->execution_stack, TRUE); - g_free(process); -} - - -static void free_process_state(gpointer key, gpointer value,gpointer user_data) -{ - g_array_free(((LttvProcessState *)value)->execution_stack, TRUE); - g_free(value); -} - - -static void lttv_state_free_process_table(GHashTable *processes) -{ - g_hash_table_foreach(processes, free_process_state, NULL); - g_hash_table_destroy(processes); -} - - -static gboolean syscall_entry(void *hook_data, void *call_data) -{ - LttField *f = ((LttvTraceHook *)hook_data)->f1; - - LttvTracefileState *s = (LttvTracefileState *)call_data; - - LttvExecutionSubmode submode; - - submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[ - ltt_event_get_unsigned(s->parent.e, f)]; - push_state(s, LTTV_STATE_SYSCALL, submode); - return FALSE; -} - - -static gboolean syscall_exit(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - - pop_state(s, LTTV_STATE_SYSCALL); - return FALSE; -} - - -static gboolean trap_entry(void *hook_data, void *call_data) -{ - LttField *f = ((LttvTraceHook *)hook_data)->f1; - - LttvTracefileState *s = (LttvTracefileState *)call_data; - - LttvExecutionSubmode submode; - - submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[ - ltt_event_get_unsigned(s->parent.e, f)]; - push_state(s, LTTV_STATE_TRAP, submode); - return FALSE; -} - - -static gboolean trap_exit(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - - pop_state(s, LTTV_STATE_TRAP); - return FALSE; -} - - -static gboolean irq_entry(void *hook_data, void *call_data) -{ - LttField *f = ((LttvTraceHook *)hook_data)->f1; - - LttvTracefileState *s = (LttvTracefileState *)call_data; - - LttvExecutionSubmode submode; - - submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[ - ltt_event_get_unsigned(s->parent.e, f)]; - - /* Do something with the info about being in user or system mode when int? */ - push_state(s, LTTV_STATE_IRQ, submode); - return FALSE; -} - - -static gboolean irq_exit(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - - pop_state(s, LTTV_STATE_IRQ); - return FALSE; -} - - -static gboolean schedchange(void *hook_data, void *call_data) -{ - LttvTraceHook *h = (LttvTraceHook *)hook_data; - - LttvTracefileState *s = (LttvTracefileState *)call_data; - - guint pid_in, pid_out, state_out; - - pid_in = ltt_event_get_unsigned(s->parent.e, h->f1); - pid_out = ltt_event_get_unsigned(s->parent.e, h->f2); - state_out = ltt_event_get_unsigned(s->parent.e, h->f3); - - if(s->process != NULL) { - - if(state_out == 0) s->process->state->s = LTTV_STATE_WAIT_CPU; - else if(s->process->state->s == LTTV_STATE_EXIT) - exit_process(s, s->process); - else s->process->state->s = LTTV_STATE_WAIT; - - if(s->process->pid == 0) - s->process->pid = pid_out; - - s->process->state->change = s->parent.timestamp; - } - s->process = lttv_state_find_process(s, pid_in); - s->process->state->s = LTTV_STATE_RUN; - s->process->state->change = s->parent.timestamp; - return FALSE; -} - - -static gboolean process_fork(void *hook_data, void *call_data) -{ - LttField *f = ((LttvTraceHook *)hook_data)->f1; - - LttvTracefileState *s = (LttvTracefileState *)call_data; - - guint child_pid; - - child_pid = ltt_event_get_unsigned(s->parent.e, f); - create_process(s, s->process, child_pid); - return FALSE; -} - - -static gboolean process_exit(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - - if(s->process != NULL) { - s->process->state->s = LTTV_STATE_EXIT; - } - return FALSE; -} - - -void lttv_state_add_event_hooks(LttvTracesetState *self) -{ - LttvTraceset *traceset = self->parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceState *ts; - - LttvTracefileState *tfs; - - GArray *hooks; - - LttvTraceHook hook; - - LttvAttributeValue val; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = (LttvTraceState *)self->parent.traces[i]; - - /* Find the eventtype id for the following events and register the - associated by id hooks. */ - - hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); - g_array_set_size(hooks, 9); - - lttv_trace_find_hook(ts->parent.t, "core","syscall_entry","syscall_id", - NULL, NULL, syscall_entry, &g_array_index(hooks, LttvTraceHook, 0)); - - lttv_trace_find_hook(ts->parent.t, "core", "syscall_exit", NULL, NULL, - NULL, syscall_exit, &g_array_index(hooks, LttvTraceHook, 1)); - - lttv_trace_find_hook(ts->parent.t, "core", "trap_entry", "trap_id", - NULL, NULL, trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); - - lttv_trace_find_hook(ts->parent.t, "core", "trap_exit", NULL, NULL, NULL, - trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); - - lttv_trace_find_hook(ts->parent.t, "core", "irq_entry", "irq_id", NULL, - NULL, irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); - - lttv_trace_find_hook(ts->parent.t, "core", "irq_exit", NULL, NULL, NULL, - irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); - - lttv_trace_find_hook(ts->parent.t, "core", "schedchange", "in", "out", - "out_state", schedchange, &g_array_index(hooks, LttvTraceHook, 6)); - - lttv_trace_find_hook(ts->parent.t, "core", "process_fork", "child_pid", - NULL, NULL, process_fork, &g_array_index(hooks, LttvTraceHook, 7)); - - lttv_trace_find_hook(ts->parent.t, "core", "process_exit", NULL, NULL, - NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 8)); - - /* Add these hooks to each before_event_by_id hooks list */ - - nb_control = ltt_trace_control_tracefile_number(ts->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); - } - else { - tfs = LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); - } - - for(k = 0 ; k < hooks->len ; k++) { - hook = g_array_index(hooks, LttvTraceHook, k); - lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, - hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k)); - } - } - lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val); - *(val.v_pointer) = hooks; - } -} - - -void lttv_state_remove_event_hooks(LttvTracesetState *self) -{ - LttvTraceset *traceset = self->parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceState *ts; - - LttvTracefileState *tfs; - - GArray *hooks; - - LttvTraceHook hook; - - LttvAttributeValue val; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = LTTV_TRACE_STATE(self->parent.traces[i]); - lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val); - hooks = *(val.v_pointer); - - /* Add these hooks to each before_event_by_id hooks list */ - - nb_control = ltt_trace_control_tracefile_number(ts->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); - } - else { - tfs = LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); - } - - for(k = 0 ; k < hooks->len ; k++) { - hook = g_array_index(hooks, LttvTraceHook, k); - lttv_hooks_remove_data( - lttv_hooks_by_id_find(tfs->parent.after_event_by_id, - hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k)); - } - } - g_array_free(hooks, TRUE); - } -} - - -static gboolean block_end(void *hook_data, void *call_data) -{ - LttvTracefileState *tfcs = (LttvTracefileState *)call_data; - - LttvTraceState *tcs = (LttvTraceState *)(tfcs->parent.t_context); - - LttEventPosition *ep = ltt_event_position_new(); - - guint nb_block, nb_event; - - LttTracefile *tf; - - LttvAttribute *saved_states_tree, *saved_state_tree; - - LttvAttributeValue value; - - ltt_event_position(tfcs->parent.e, ep); - - ltt_event_position_get(ep, &nb_block, &nb_event, &tf); - tcs->nb_event += nb_event - tfcs->saved_position; - tfcs->saved_position = 0; - if(tcs->nb_event >= tcs->save_interval) { - saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, - LTTV_STATE_SAVED_STATES); - saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - value = lttv_attribute_add(saved_states_tree, - lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT); - *(value.v_gobject) = (GObject *)saved_state_tree; - value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME); - *(value.v_time) = tfcs->parent.timestamp; - lttv_state_save(tcs, saved_state_tree); - tcs->nb_event = 0; - } - return FALSE; -} - - -void lttv_state_save_add_event_hooks(LttvTracesetState *self) -{ - LttvTraceset *traceset = self->parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceState *ts; - - LttvTracefileState *tfs; - - LttvTraceHook hook; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = (LttvTraceState *)self->parent.traces[i]; - lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, - NULL, NULL, block_end, &hook); - - nb_control = ltt_trace_control_tracefile_number(ts->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); - } - else { - tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); - } - - lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, - hook.id), hook.h, NULL); - } - } -} - - -void lttv_state_save_remove_event_hooks(LttvTracesetState *self) -{ - LttvTraceset *traceset = self->parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceState *ts; - - LttvTracefileState *tfs; - - LttvTraceHook hook; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = LTTV_TRACE_STATE(self->parent.traces[i]); - lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, - NULL, NULL, block_end, &hook); - - nb_control = ltt_trace_control_tracefile_number(ts->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); - } - else { - tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); - } - - lttv_hooks_remove_data(lttv_hooks_by_id_find( - tfs->parent.after_event_by_id, hook.id), hook.h, NULL); - } - } -} - - -void lttv_state_restore_closest_state(LttvTracesetState *self, LttTime t) -{ - LttvTraceset *traceset = self->parent.ts; - - guint i, j, nb_trace, nb_saved_state; - - int min_pos, mid_pos, max_pos; - - LttvTraceState *tcs; - - LttvAttributeValue value; - - LttvAttributeType type; - - LttvAttributeName name; - - LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceState *)self->parent.traces[i]; - - saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, - LTTV_STATE_SAVED_STATES); - min_pos = -1; - max_pos = lttv_attribute_get_number(saved_states_tree) - 1; - mid_pos = max_pos / 2; - while(min_pos < max_pos) { - type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value); - g_assert(type == LTTV_GOBJECT); - saved_state_tree = *((LttvAttribute **)(value.v_gobject)); - type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME, - &value); - g_assert(type == LTTV_TIME); - if(ltt_time_compare(*(value.v_time), t) < 0) { - min_pos = mid_pos; - closest_tree = saved_state_tree; - } - else max_pos = mid_pos - 1; - - mid_pos = (min_pos + max_pos + 1) / 2; - } - if(min_pos == -1) { - restore_init_state(tcs); - lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero); - } - else lttv_state_restore(tcs, closest_tree); - } -} - - -static void -traceset_state_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -traceset_state_finalize (LttvTracesetState *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -traceset_state_class_init (LttvTracesetContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize; - klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init; - klass->fini = (void (*)(LttvTracesetContext *self))fini; - klass->new_traceset_context = new_traceset_context; - klass->new_trace_context = new_trace_context; - klass->new_tracefile_context = new_tracefile_context; -} - - -GType -lttv_traceset_state_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracesetStateClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) traceset_state_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracesetContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) traceset_state_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType", - &info, 0); - } - return type; -} - - -static void -trace_state_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -trace_state_finalize (LttvTraceState *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -trace_state_class_init (LttvTraceStateClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize; - klass->state_save = state_save; - klass->state_restore = state_restore; - klass->state_saved_free = state_saved_free; -} - - -GType -lttv_trace_state_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTraceStateClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) trace_state_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTraceState), - 0, /* n_preallocs */ - (GInstanceInitFunc) trace_state_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE, - "LttvTraceStateType", &info, 0); - } - return type; -} - - -static void -tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -tracefile_state_finalize (LttvTracefileState *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -tracefile_state_class_init (LttvTracefileStateClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize; -} - - -GType -lttv_tracefile_state_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracefileStateClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) tracefile_state_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracefileState), - 0, /* n_preallocs */ - (GInstanceInitFunc) tracefile_state_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE, - "LttvTracefileStateType", &info, 0); - } - return type; -} - - -void lttv_state_init(int argc, char **argv) -{ - LTTV_STATE_UNNAMED = g_quark_from_string("unnamed"); - LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode"); - LTTV_STATE_USER_MODE = g_quark_from_string("user mode"); - LTTV_STATE_WAIT_FORK = g_quark_from_string("wait fork"); - LTTV_STATE_SYSCALL = g_quark_from_string("system call"); - LTTV_STATE_TRAP = g_quark_from_string("trap"); - LTTV_STATE_IRQ = g_quark_from_string("irq"); - LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("unknown submode"); - LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)"); - LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu"); - LTTV_STATE_EXIT = g_quark_from_string("exiting"); - LTTV_STATE_WAIT = g_quark_from_string("wait for I/O"); - LTTV_STATE_RUN = g_quark_from_string("running"); - LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles"); - LTTV_STATE_PROCESSES = g_quark_from_string("processes"); - LTTV_STATE_PROCESS = g_quark_from_string("process"); - LTTV_STATE_EVENT = g_quark_from_string("event"); - LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states"); - LTTV_STATE_TIME = g_quark_from_string("time"); - LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks"); -} - -void lttv_state_destroy() -{ -} - - - - diff --git a/ltt/branches/poly/lttv/stats.c b/ltt/branches/poly/lttv/stats.c deleted file mode 100644 index 4265853d..00000000 --- a/ltt/branches/poly/lttv/stats.c +++ /dev/null @@ -1,1180 +0,0 @@ - -#include -#include -#include -#include -#include - -#define BUF_SIZE 256 - -GQuark - LTTV_STATS_PROCESS_UNKNOWN, - LTTV_STATS_PROCESSES, - LTTV_STATS_CPU, - LTTV_STATS_MODE_TYPES, - LTTV_STATS_MODES, - LTTV_STATS_SUBMODES, - LTTV_STATS_EVENT_TYPES, - LTTV_STATS_CPU_TIME, - LTTV_STATS_ELAPSED_TIME, - LTTV_STATS_EVENTS, - LTTV_STATS_EVENTS_COUNT; - -static GQuark - LTTV_STATS_BEFORE_HOOKS, - LTTV_STATS_AFTER_HOOKS; - -static void remove_all_processes(GHashTable *processes); - -static void -find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu, - GQuark mode, GQuark sub_mode, LttvAttribute **events_tree, - LttvAttribute **event_types_tree); - -static void -init(LttvTracesetStats *self, LttvTraceset *ts) -{ - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTraceStats *tcs; - - LttvTracefileContext *tfc; - - LttvTracefileStats *tfcs; - - LttTime timestamp = {0,0}; - - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> - init((LttvTracesetContext *)self, ts); - - self->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - nb_trace = lttv_traceset_number(ts); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); - tcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfcs = LTTV_TRACEFILE_STATS(tc->control_tracefiles[j]); - } - else { - tfcs = LTTV_TRACEFILE_STATS(tc->per_cpu_tracefiles[j - nb_control]); - } - - tfcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN, - tfcs->parent.cpu_name, LTTV_STATE_MODE_UNKNOWN, - LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree, - &tfcs->current_event_types_tree); - } - } -} - - -static void -fini(LttvTracesetStats *self) -{ - guint i, j, nb_trace, nb_tracefile; - - LttvTraceset *ts; - - LttvTraceContext *tc; - - LttvTraceStats *tcs; - - LttvTracefileContext *tfc; - - LttvTracefileStats *tfcs; - - LttTime timestamp = {0,0}; - - lttv_attribute_recursive_free(self->stats); - ts = self->parent.parent.ts; - nb_trace = lttv_traceset_number(ts); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); - lttv_attribute_recursive_free(tcs->stats); - - nb_tracefile = ltt_trace_control_tracefile_number(tc->t); - for(j = 0 ; j < nb_tracefile ; j++) { - tfcs = (LttvTracefileStats *)tfc = tc->control_tracefiles[j]; - lttv_attribute_recursive_free(tfcs->stats); - tfcs->current_events_tree = NULL; - tfcs->current_event_types_tree = NULL; - } - - nb_tracefile = ltt_trace_per_cpu_tracefile_number(tc->t); - for(j = 0 ; j < nb_tracefile ; j++) { - tfcs = (LttvTracefileStats *)tfc = tc->per_cpu_tracefiles[j]; - lttv_attribute_recursive_free(tfcs->stats); - tfcs->current_events_tree = NULL; - tfcs->current_event_types_tree = NULL; - } - } - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> - fini((LttvTracesetContext *)self); -} - - -static LttvTracesetContext * -new_traceset_context(LttvTracesetContext *self) -{ - return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL)); -} - - -static LttvTraceContext * -new_trace_context(LttvTracesetContext *self) -{ - return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL)); -} - - -static LttvTracefileContext * -new_tracefile_context(LttvTracesetContext *self) -{ - return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL)); -} - - -static void -traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -traceset_stats_finalize (LttvTracesetStats *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -traceset_stats_class_init (LttvTracesetContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize; - klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init; - klass->fini = (void (*)(LttvTracesetContext *self))fini; - klass->new_traceset_context = new_traceset_context; - klass->new_trace_context = new_trace_context; - klass->new_tracefile_context = new_tracefile_context; -} - - -GType -lttv_traceset_stats_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracesetStatsClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) traceset_stats_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracesetContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) traceset_stats_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACESET_STATE_TYPE, "LttvTracesetStatsType", - &info, 0); - } - return type; -} - - -static void -trace_stats_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -trace_stats_finalize (LttvTraceStats *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -trace_stats_class_init (LttvTraceContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize; -} - - -GType -lttv_trace_stats_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTraceStatsClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) trace_stats_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTraceStats), - 0, /* n_preallocs */ - (GInstanceInitFunc) trace_stats_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACE_STATE_TYPE, - "LttvTraceStatsType", &info, 0); - } - return type; -} - - -static void -tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -tracefile_stats_finalize (LttvTracefileStats *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -tracefile_stats_class_init (LttvTracefileStatsClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize; -} - - -GType -lttv_tracefile_stats_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracefileStatsClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) tracefile_stats_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracefileStats), - 0, /* n_preallocs */ - (GInstanceInitFunc) tracefile_stats_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE, - "LttvTracefileStatsType", &info, 0); - } - return type; -} - - -static void -find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu, - GQuark mode, GQuark sub_mode, LttvAttribute **events_tree, - LttvAttribute **event_types_tree) -{ - LttvAttribute *a; - - LttvTraceStats *tcs = LTTV_TRACE_STATS(tfcs->parent.parent.t_context); - a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES); - a = lttv_attribute_find_subdir(a, tfcs->parent.process->pid_time); - a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU); - a = lttv_attribute_find_subdir(a, tfcs->parent.cpu_name); - a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES); - a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->t); - a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES); - a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->n); - *events_tree = a; - a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES); - *event_types_tree = a; -} - - -static void update_event_tree(LttvTracefileStats *tfcs) -{ - LttvExecutionState *es = tfcs->parent.process->state; - - find_event_tree(tfcs, tfcs->parent.process->pid_time, tfcs->parent.cpu_name, - es->t, es->n, &(tfcs->current_events_tree), - &(tfcs->current_event_types_tree)); -} - - -static void mode_change(LttvTracefileStats *tfcs) -{ - LttvAttributeValue cpu_time; - - LttTime delta; - - lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, - LTTV_TIME, &cpu_time); - delta = ltt_time_sub(tfcs->parent.parent.timestamp, - tfcs->parent.process->state->change); - *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta); -} - - -static void mode_end(LttvTracefileStats *tfcs) -{ - LttvAttributeValue elapsed_time, cpu_time; - - LttTime delta; - - lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME, - LTTV_TIME, &elapsed_time); - delta = ltt_time_sub(tfcs->parent.parent.timestamp, - tfcs->parent.process->state->entry); - *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta); - - lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, - LTTV_TIME, &cpu_time); - delta = ltt_time_sub(tfcs->parent.parent.timestamp, - tfcs->parent.process->state->change); - *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta); -} - - -static gboolean before_syscall_entry(void *hook_data, void *call_data) -{ - mode_change((LttvTracefileStats *)call_data); - return FALSE; -} - - -static gboolean after_syscall_entry(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_syscall_exit(void *hook_data, void *call_data) -{ - mode_end((LttvTracefileStats *)call_data); - return FALSE; -} - - -static gboolean after_syscall_exit(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_trap_entry(void *hook_data, void *call_data) -{ - mode_change((LttvTracefileStats *)call_data); - return FALSE; -} - - -static gboolean after_trap_entry(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_trap_exit(void *hook_data, void *call_data) -{ - mode_end((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean after_trap_exit(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_irq_entry(void *hook_data, void *call_data) -{ - mode_change((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean after_irq_entry(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_irq_exit(void *hook_data, void *call_data) -{ - mode_end((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean after_irq_exit(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_schedchange(void *hook_data, void *call_data) -{ - LttvTraceHook *h = (LttvTraceHook *)hook_data; - - LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data; - - guint pid_in, pid_out, state_out; - - LttvProcessState *process; - - pid_in = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f1); - pid_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f2); - state_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f3); - - /* compute the time for the process to schedule out */ - - mode_change(tfcs); - - /* get the information for the process scheduled in */ - - process = lttv_state_find_process(&(tfcs->parent), pid_in); - - find_event_tree(tfcs, process->pid_time, tfcs->parent.cpu_name, - process->state->t, process->state->n, &(tfcs->current_events_tree), - &(tfcs->current_event_types_tree)); - - /* compute the time waiting for the process to schedule in */ - - mode_change(tfcs); - return FALSE; -} - - -gboolean process_fork(void *hook_data, void *call_data) -{ - /* nothing to do for now */ - return FALSE; -} - - -gboolean process_exit(void *hook_data, void *call_data) -{ - /* We should probably exit all modes here or we could do that at - schedule out. */ - return FALSE; -} - - -gboolean every_event(void *hook_data, void *call_data) -{ - LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data; - - LttvAttributeValue v; - - /* The current branch corresponds to the tracefile/process/interrupt state. - Statistics are added within it, to count the number of events of this - type occuring in this context. A quark has been pre-allocated for each - event type and is used as name. */ - - lttv_attribute_find(tfcs->current_event_types_tree, - ((LttvTraceState *)(tfcs->parent.parent.t_context))-> - eventtype_names[ltt_event_eventtype_id(tfcs->parent.parent.e)], - LTTV_UINT, &v); - (*(v.v_uint))++; - return FALSE; -} - - -static gboolean -sum_stats(void *hook_data, void *call_data) -{ - LttvTracesetStats *tscs = (LttvTracesetStats *)call_data; - - LttvTraceStats *tcs; - - LttvTraceset *traceset = tscs->parent.parent.ts; - - LttvAttributeType type; - - LttvAttributeValue value; - - LttvAttributeName name; - - unsigned sum; - - int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode, - nb_event_type; - - LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, - *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, - *submode_tree, *event_types_tree, *mode_events_tree, - *cpu_events_tree, *process_modes_tree, *trace_cpu_tree, - *trace_modes_tree, *traceset_modes_tree; - - traceset_modes_tree = lttv_attribute_find_subdir(tscs->stats, - LTTV_STATS_MODES); - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - main_tree = tcs->stats; - processes_tree = lttv_attribute_find_subdir(main_tree, - LTTV_STATS_PROCESSES); - trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES); - nb_process = lttv_attribute_get_number(processes_tree); - - for(j = 0 ; j < nb_process ; j++) { - type = lttv_attribute_get(processes_tree, j, &name, &value); - process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); - process_modes_tree = lttv_attribute_find_subdir(process_tree, - LTTV_STATS_MODES); - nb_cpu = lttv_attribute_get_number(cpus_tree); - - for(k = 0 ; k < nb_cpu ; k++) { - type = lttv_attribute_get(cpus_tree, k, &name, &value); - cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - mode_types_tree = lttv_attribute_find_subdir(cpu_tree, - LTTV_STATS_MODE_TYPES); - cpu_events_tree = lttv_attribute_find_subdir(cpu_tree, - LTTV_STATS_EVENTS); - trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU); - trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name); - nb_mode_type = lttv_attribute_get_number(mode_types_tree); - - for(l = 0 ; l < nb_mode_type ; l++) { - type = lttv_attribute_get(mode_types_tree, l, &name, &value); - mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - submodes_tree = lttv_attribute_find_subdir(mode_tree, - LTTV_STATS_SUBMODES); - mode_events_tree = lttv_attribute_find_subdir(mode_tree, - LTTV_STATS_EVENTS); - nb_submode = lttv_attribute_get_number(submodes_tree); - - for(m = 0 ; m < nb_submode ; m++) { - type = lttv_attribute_get(submodes_tree, m, &name, &value); - submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - event_types_tree = lttv_attribute_find_subdir(submode_tree, - LTTV_STATS_EVENT_TYPES); - nb_event_type = lttv_attribute_get_number(event_types_tree); - - sum = 0; - for(n = 0 ; n < nb_event_type ; n++) { - type = lttv_attribute_get(event_types_tree, n, &name, &value); - sum += *(value.v_uint); - } - lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT, - LTTV_UINT, &value); - *(value.v_uint) = sum; - lttv_attribute_recursive_add(mode_events_tree, submode_tree); - } - lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree); - } - lttv_attribute_recursive_add(process_modes_tree, cpu_tree); - lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree); - } - lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree); - } - lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree); - } - return FALSE; -} - - -lttv_stats_add_event_hooks(LttvTracesetStats *self) -{ - LttvTraceset *traceset = self->parent.parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttFacility *f; - - LttEventType *et; - - LttvTraceStats *ts; - - LttvTracefileStats *tfs; - - void *hook_data; - - GArray *hooks, *before_hooks, *after_hooks; - - LttvTraceHook hook; - - LttvAttributeValue val; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = (LttvTraceStats *)self->parent.parent.traces[i]; - - /* Find the eventtype id for the following events and register the - associated by id hooks. */ - - hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); - g_array_set_size(hooks, 7); - - lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry", - "syscall_id", NULL, NULL, before_syscall_entry, - &g_array_index(hooks, LttvTraceHook, 0)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL, - NULL, NULL, before_syscall_exit, - &g_array_index(hooks, LttvTraceHook, 1)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id", - NULL, NULL, before_trap_entry, - &g_array_index(hooks, LttvTraceHook, 2)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL, - NULL, before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id", - NULL, NULL, before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL, - NULL, before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "schedchange", "in", - "out", "out_state", before_schedchange, - &g_array_index(hooks, LttvTraceHook, 6)); - - before_hooks = hooks; - - hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); - g_array_set_size(hooks, 8); - - lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry", - "syscall_id", NULL, NULL, after_syscall_entry, - &g_array_index(hooks, LttvTraceHook, 0)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL, - NULL, NULL, after_syscall_exit, - &g_array_index(hooks, LttvTraceHook, 1)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id", - NULL, NULL, after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL, - NULL, after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id", - NULL, NULL, after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL, - NULL, after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "process_fork", - "child_pid", NULL, NULL, process_fork, - &g_array_index(hooks, LttvTraceHook, 6)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "process_exit", NULL, - NULL, NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 7)); - - after_hooks = hooks; - - /* Add these hooks to each before_event_by_id hooks list */ - - nb_control = ltt_trace_control_tracefile_number(ts->parent.parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.control_tracefiles[j]); - } - else { - tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.per_cpu_tracefiles[ - j-nb_control]); - } - - lttv_hooks_add(tfs->parent.parent.after_event, every_event, NULL); - - for(k = 0 ; k < before_hooks->len ; k++) { - hook = g_array_index(before_hooks, LttvTraceHook, k); - lttv_hooks_add(lttv_hooks_by_id_find( - tfs->parent.parent.before_event_by_id, - hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k)); - } - for(k = 0 ; k < after_hooks->len ; k++) { - hook = g_array_index(after_hooks, LttvTraceHook, k); - lttv_hooks_add(lttv_hooks_by_id_find( - tfs->parent.parent.after_event_by_id, - hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k)); - } - } - lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS, - LTTV_POINTER, &val); - *(val.v_pointer) = before_hooks; - lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS, - LTTV_POINTER, &val); - *(val.v_pointer) = after_hooks; - } - lttv_hooks_add(self->parent.parent.after, sum_stats, NULL); -} - - -lttv_stats_remove_event_hooks(LttvTracesetStats *self) -{ - LttvTraceset *traceset = self->parent.parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceStats *ts; - - LttvTracefileStats *tfs; - - void *hook_data; - - GArray *before_hooks, *after_hooks; - - LttvTraceHook hook; - - LttvAttributeValue val; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = LTTV_TRACE_STATS(self->parent.parent.traces[i]); - lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS, - LTTV_POINTER, &val); - before_hooks = *(val.v_pointer); - lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS, - LTTV_POINTER, &val); - after_hooks = *(val.v_pointer); - - /* Add these hooks to each before_event_by_id hooks list */ - - nb_control = ltt_trace_control_tracefile_number(ts->parent.parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.control_tracefiles[j]); - } - else { - tfs =LTTV_TRACEFILE_STATS(ts->parent.parent.per_cpu_tracefiles[ - j-nb_control]); - } - - lttv_hooks_remove_data(tfs->parent.parent.after_event, every_event, - NULL); - - for(k = 0 ; k < before_hooks->len ; k++) { - hook = g_array_index(before_hooks, LttvTraceHook, k); - lttv_hooks_remove_data( - lttv_hooks_by_id_find(tfs->parent.parent.before_event_by_id, - hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k)); - } - for(k = 0 ; k < after_hooks->len ; k++) { - hook = g_array_index(after_hooks, LttvTraceHook, k); - lttv_hooks_remove_data( - lttv_hooks_by_id_find(tfs->parent.parent.after_event_by_id, - hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k)); - } - } - g_critical("lttv_stats_remove_event_hooks()"); - g_array_free(before_hooks, TRUE); - g_array_free(after_hooks, TRUE); - } - lttv_hooks_remove_data(self->parent.parent.after, sum_stats, NULL); -} - - -void lttv_stats_init(int argc, char **argv) -{ - LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process"); - LTTV_STATS_PROCESSES = g_quark_from_string("processes"); - LTTV_STATS_CPU = g_quark_from_string("cpu"); - LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types"); - LTTV_STATS_MODES = g_quark_from_string("modes"); - LTTV_STATS_SUBMODES = g_quark_from_string("submodes"); - LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types"); - LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time"); - LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time"); - LTTV_STATS_EVENTS = g_quark_from_string("events"); - LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count"); - LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks"); - LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks"); -} - -void lttv_stats_destroy() -{ -} - -void lttv_stats_save_attribute(LttvAttribute *attr, char *indent, FILE * fp) -{ - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - char type_value[BUF_SIZE]; - int i, nb_attr, flag; - - nb_attr = lttv_attribute_get_number(attr); - for(i=0;itv_sec, - value.v_time->tv_nsec); - break; - case LTTV_POINTER: - sprintf(type_value, "POINTER\0"); - break; - case LTTV_STRING: - sprintf(type_value, "%s\0", *value.v_string); - break; - default: - flag = 0; - break; - } - if(flag == 0) continue; - fprintf(fp,"%s",indent,type,g_quark_to_string(name)); - fprintf(fp,"%s",type_value); - fprintf(fp," \n"); - } - -} - -void lttv_stats_save_statistics(LttvTracesetStats *self) -{ - LttvTracesetStats *tscs = self; - LttvTraceStats *tcs; - LttvTraceset *traceset = tscs->parent.parent.ts; - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - - char filename[BUF_SIZE]; - FILE * fp; - char indent[10][24]= {" ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " " - }; - - - int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode; - - LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, - *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, - *submode_tree, *event_types_tree; - - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - - filename[0] = '\0'; - strcat(filename,ltt_trace_name(tcs->parent.parent.t)); - strcat(filename,"/statistics.xml"); - fp = fopen(filename,"w"); - if(!fp){ - g_warning("can not open the file %s for saving statistics\n", filename); - exit(1); - } - - main_tree = tcs->stats; - processes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_PROCESSES); - nb_process = lttv_attribute_get_number(processes_tree); - - fprintf(fp, " \n",g_quark_to_string(LTTV_STATS_PROCESSES)); //root NODE - - for(j = 0 ; j < nb_process ; j++) { - type = lttv_attribute_get(processes_tree, j, &name, &value); - process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[0],g_quark_to_string(name)); //process NODE - lttv_stats_save_attribute(process_tree,indent[1], fp); - fprintf(fp,"%s \n", indent[1],g_quark_to_string(LTTV_STATS_CPU)); //cpus NODE - - cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); - nb_cpu = lttv_attribute_get_number(cpus_tree); - - for(k = 0 ; k < nb_cpu ; k++) { - type = lttv_attribute_get(cpus_tree, k, &name, &value); - cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[2],g_quark_to_string(name)); //cpu NODE - lttv_stats_save_attribute(cpu_tree,indent[3], fp); - fprintf(fp,"%s \n",indent[3],g_quark_to_string(LTTV_STATS_MODE_TYPES)); //mode_types NODE - - mode_types_tree = lttv_attribute_find_subdir(cpu_tree,LTTV_STATS_MODE_TYPES); - nb_mode_type = lttv_attribute_get_number(mode_types_tree); - - for(l = 0 ; l < nb_mode_type ; l++) { - type = lttv_attribute_get(mode_types_tree, l, &name, &value); - mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[4],g_quark_to_string(name)); //mode NODE - lttv_stats_save_attribute(mode_tree,indent[5], fp); - fprintf(fp,"%s \n",indent[5],g_quark_to_string(LTTV_STATS_SUBMODES)); //sub_modes NODE - - submodes_tree = lttv_attribute_find_subdir(mode_tree,LTTV_STATS_SUBMODES); - nb_submode = lttv_attribute_get_number(submodes_tree); - - for(m = 0 ; m < nb_submode ; m++) { - type = lttv_attribute_get(submodes_tree, m, &name, &value); - submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - fprintf(fp,"%s \n",indent[6],g_quark_to_string(name)); //sub_mode NODE - lttv_stats_save_attribute(submode_tree,indent[7], fp); - fprintf(fp,"%s \n",indent[7],g_quark_to_string(LTTV_STATS_EVENT_TYPES)); //event_types NODE - - event_types_tree = lttv_attribute_find_subdir(submode_tree, LTTV_STATS_EVENT_TYPES); - lttv_stats_save_attribute(event_types_tree,indent[8], fp); - - fprintf(fp,"%s \n",indent[7]); //event_types NODE - fprintf(fp,"%s \n",indent[6]); //sub_mode NODE - } - fprintf(fp,"%s \n",indent[5]); //sub_modes NODE - fprintf(fp,"%s \n",indent[4]); //mode NODE - } - fprintf(fp,"%s \n",indent[3]); //mode_type NODE - fprintf(fp,"%s \n",indent[2]); //cpu NODE - } - fprintf(fp,"%s \n",indent[1]); //cpus NODE - fprintf(fp,"%s \n", indent[0]); //process NODE - } - fprintf(fp, "\n"); //root NODE - fclose(fp); - } -} - - -/* Functions to parse statistic.xml file (using glib xml parser) */ - -typedef struct _ParserStruct{ - GPtrArray * attribute; - LttvAttributeType type; - LttvAttributeName name; -} ParserStruct; - -static void stats_parser_start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - int len; - LttvAttributeType type; - LttvAttributeName name; - LttvAttribute * parent_att, *new_att; - - len = parser->attribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - - if(strcmp("NODE", element_name) == 0){ - type = LTTV_GOBJECT; - name = g_quark_from_string(attribute_values[0]); - new_att = lttv_attribute_find_subdir(parent_att,name); - g_ptr_array_add(parser->attribute, (gpointer)new_att); - }else if(strcmp("VALUE", element_name) == 0){ - parser->type = (LttvAttributeType) atoi(attribute_values[0]); - parser->name = g_quark_from_string(attribute_values[1]); - }else{ - g_warning("This is not statistics.xml file\n"); - exit(1); - } -} - -static void stats_parser_end_element (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - int len; - LttvAttribute * parent_att; - - len = parser->attribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - - if(strcmp("NODE", element_name) == 0){ - g_ptr_array_remove_index(parser->attribute, len-1); - }else if(strcmp("VALUE", element_name) == 0){ - }else{ - g_warning("This is not statistics.xml file\n"); - exit(1); - } - -} - -static void stats_parser_characters (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - LttvAttributeValue value; - int len; - LttvAttribute * parent_att; - char *pos; - - pos = (char*)text; - for(len=0;lenattribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - if(!lttv_attribute_find(parent_att,parser->name, parser->type, &value)){ - g_warning("can not find value\n"); - exit(1); - } - - switch(parser->type) { - case LTTV_INT: - *value.v_int = atoi(text); - break; - case LTTV_UINT: - *value.v_uint = (unsigned)atoi(text); - break; - case LTTV_LONG: - *value.v_long = atol(text); - break; - case LTTV_ULONG: - *value.v_ulong = (unsigned long)atol(text); - break; - case LTTV_FLOAT: - *value.v_float = atof(text); - break; - case LTTV_DOUBLE: - *value.v_float = atof(text); - break; - case LTTV_TIME: - pos = strrchr(text,'.'); - if(pos){ - *pos = '\0'; - pos++; - value.v_time->tv_sec = atol(text); - value.v_time->tv_nsec = atol(pos); - }else{ - g_warning("The time value format is wrong\n"); - exit(1); - } - break; - case LTTV_POINTER: - break; - case LTTV_STRING: - *value.v_string = g_strdup(text); - break; - default: - break; - } - -} - -gboolean lttv_stats_load_statistics(LttvTracesetStats *self) -{ - FILE * fp; - char buf[BUF_SIZE]; - LttvTracesetStats *tscs = self; - LttvTraceStats *tcs; - LttvTraceset *traceset = tscs->parent.parent.ts; - char filename[BUF_SIZE]; - - GMarkupParseContext * context; - GError * error; - GMarkupParser markup_parser = - { - stats_parser_start_element, - stats_parser_end_element, - stats_parser_characters, - NULL, /* passthrough */ - NULL /* error */ - }; - - int i, nb_trace; - LttvAttribute *main_tree; - ParserStruct a_parser_struct; - a_parser_struct.attribute = g_ptr_array_new(); - - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - - filename[0] = '\0'; - strcat(filename,ltt_trace_name(tcs->parent.parent.t)); - strcat(filename,"/statistics.xml"); - fp = fopen(filename,"r"); - if(!fp){ - g_warning("can not open the file %s for reading statistics\n", filename); - return FALSE; - } - - main_tree = tcs->stats; - g_ptr_array_add(a_parser_struct.attribute,(gpointer)main_tree); - - context = g_markup_parse_context_new(&markup_parser, 0, (gpointer)&a_parser_struct, NULL); - - while(fgets(buf,BUF_SIZE, fp) != NULL){ - if(!g_markup_parse_context_parse(context, buf, BUF_SIZE, &error)){ - g_warning("Can not parse xml file: \n%s\n", error->message); - exit(1); - } - } - fclose(fp); - } - - sum_stats(NULL, (void *)self); - - return TRUE; -} diff --git a/ltt/branches/poly/lttv/textDump.c b/ltt/branches/poly/lttv/textDump.c deleted file mode 100644 index 24b266a2..00000000 --- a/ltt/branches/poly/lttv/textDump.c +++ /dev/null @@ -1,405 +0,0 @@ -/* The text dump facility needs to print headers before the trace set and - before each trace, to print each event, and to print statistics - after each trace. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static gboolean - a_field_names, - a_state, - a_cpu_stats, - a_process_stats; - -static char - *a_file_name = NULL; - -static LttvHooks - *before_traceset, - *after_traceset, - *before_trace, - *before_event; - - -void print_field(LttEvent *e, LttField *f, GString *s, gboolean field_names) { - - LttType *type; - - LttField *element; - - char *name; - - 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, - ltt_event_get_unsigned(e,f)-1)); - 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, field_names); - } - 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); - if(field_names) { - ltt_type_member_type(type, i, &name); - g_string_append_printf(s, " %s = ", name); - } - print_field(e, element, s, field_names); - } - g_string_append_printf(s, " }"); - break; - } -} - - -void lttv_event_to_string(LttEvent *e, LttTracefile *tf, GString *s, - gboolean mandatory_fields, gboolean field_names, LttvTracefileState *tfs) -{ - LttFacility *facility; - - LttEventType *event_type; - - LttType *type; - - LttField *field; - - LttTime time; - - g_string_set_size(s,0); - - facility = ltt_event_facility(e); - event_type = 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.%09ld (%s)", - ltt_facility_name(facility), - ltt_eventtype_name(event_type), (long)time.tv_sec, time.tv_nsec, - g_quark_to_string(tfs->cpu_name)); - /* Print the process id and the state/interrupt type of the process */ - g_string_append_printf(s,", %u, %u, %s", tfs->process->pid, - tfs->process->ppid, - g_quark_to_string(tfs->process->state->t)); - } - - if(field) - print_field(e, field, s, field_names); -} - - -static void -print_tree(FILE *fp, GString *indent, LttvAttribute *tree) -{ - int i, nb, saved_length; - - LttvAttribute *subtree; - - LttvAttributeName name; - - LttvAttributeValue value; - - LttvAttributeType type; - - nb = lttv_attribute_get_number(tree); - for(i = 0 ; i < nb ; i++) { - type = lttv_attribute_get(tree, i, &name, &value); - fprintf(fp, "%s%s: ", indent->str, g_quark_to_string(name)); - - switch(type) { - case LTTV_INT: - fprintf(fp, "%d\n", *value.v_int); - break; - case LTTV_UINT: - fprintf(fp, "%u\n", *value.v_uint); - break; - case LTTV_LONG: - fprintf(fp, "%ld\n", *value.v_long); - break; - case LTTV_ULONG: - fprintf(fp, "%lu\n", *value.v_ulong); - break; - case LTTV_FLOAT: - fprintf(fp, "%f\n", (double)*value.v_float); - break; - case LTTV_DOUBLE: - fprintf(fp, "%f\n", *value.v_double); - break; - case LTTV_TIME: - fprintf(fp, "%10u.%09u\n", value.v_time->tv_sec, - value.v_time->tv_nsec); - break; - case LTTV_POINTER: - fprintf(fp, "POINTER\n"); - break; - case LTTV_STRING: - fprintf(fp, "%s\n", *value.v_string); - break; - case LTTV_GOBJECT: - if(LTTV_IS_ATTRIBUTE(*(value.v_gobject))) { - fprintf(fp, "\n"); - subtree = (LttvAttribute *)*(value.v_gobject); - saved_length = indent->len; - g_string_append(indent, " "); - print_tree(fp, indent, subtree); - g_string_truncate(indent, saved_length); - } - else fprintf(fp, "GOBJECT\n"); - break; - case LTTV_NONE: - break; - } - } -} - - -static void -print_stats(FILE *fp, LttvTracesetStats *tscs) -{ - int i, nb, saved_length; - - LttvTraceset *ts; - - LttvTraceStats *tcs; - - GString *indent; - - LttSystemDescription *desc; - - if(tscs->stats == NULL) return; - indent = g_string_new(""); - fprintf(fp, "Traceset statistics:\n\n"); - print_tree(fp, indent, tscs->stats); - - ts = tscs->parent.parent.ts; - nb = lttv_traceset_number(ts); - - for(i = 0 ; i < nb ; i++) { - tcs = (LttvTraceStats *)(LTTV_TRACESET_CONTEXT(tscs)->traces[i]); - desc = ltt_trace_system_description(tcs->parent.parent.t); - fprintf(fp, "Trace on system %s at time %d secs:\n", - ltt_trace_system_description_node_name(desc), - (ltt_trace_system_description_trace_start_time(desc)).tv_sec); - saved_length = indent->len; - g_string_append(indent, " "); - print_tree(fp, indent, tcs->stats); - g_string_truncate(indent, saved_length); - } - g_string_free(indent, TRUE); -} - - -/* Insert the hooks before and after each trace and tracefile, and for each - event. Print a global header. */ - -static FILE *a_file; - -static GString *a_string; - -static gboolean write_traceset_header(void *hook_data, void *call_data) -{ - LttvTracesetContext *tc = (LttvTracesetContext *)call_data; - - g_info("TextDump traceset header"); - - if(a_file_name == NULL) a_file = stdout; - else a_file = fopen(a_file_name, "w"); - - if(a_file == NULL) g_error("cannot open file %s", a_file_name); - - /* Print the trace set header */ - fprintf(a_file,"Trace set contains %d traces\n\n", - lttv_traceset_number(tc->ts)); - - return FALSE; -} - - -static gboolean write_traceset_footer(void *hook_data, void *call_data) -{ - LttvTracesetContext *tc = (LttvTracesetContext *)call_data; - - g_info("TextDump traceset footer"); - - fprintf(a_file,"End trace set\n\n"); - - if(LTTV_IS_TRACESET_STATS(tc)) { - print_stats(a_file, (LttvTracesetStats *)tc); - } - - if(a_file_name != NULL) fclose(a_file); - - return FALSE; -} - - -static gboolean write_trace_header(void *hook_data, void *call_data) -{ - LttvTraceContext *tc = (LttvTraceContext *)call_data; - - LttSystemDescription *system = ltt_trace_system_description(tc->t); - - fprintf(a_file," Trace from %s in %s\n%s\n\n", - ltt_trace_system_description_node_name(system), - ltt_trace_system_description_domain_name(system), - ltt_trace_system_description_description(system)); - return FALSE; -} - - -static int write_event_content(void *hook_data, void *call_data) -{ - LttvTracefileContext *tfc = (LttvTracefileContext *)call_data; - - LttvTracefileState *tfs = (LttvTracefileState *)call_data; - - LttEvent *e; - - e = tfc->e; - - lttv_event_to_string(e, tfc->tf, a_string, TRUE, a_field_names, tfs); - g_string_append_printf(a_string,"\n"); - - if(a_state) { - g_string_append_printf(a_string, " %s ", - g_quark_to_string(tfs->process->state->s)); - } - - fputs(a_string->str, a_file); - return FALSE; -} - - -G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv) -{ - LttvAttributeValue value; - - LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); - - g_info("Init textDump.c"); - - lttv_module_require(self, "libbatchAnalysis", argc, argv); - - a_string = g_string_new(""); - - a_file_name = NULL; - lttv_option_add("output", 'o', - "output file where the text is written", - "file name", - LTTV_OPT_STRING, &a_file_name, NULL, NULL); - - a_field_names = FALSE; - lttv_option_add("field_names", 'l', - "write the field names for each event", - "", - LTTV_OPT_NONE, &a_field_names, NULL, NULL); - - a_state = FALSE; - lttv_option_add("process_state", 's', - "write the pid and state for each event", - "", - LTTV_OPT_NONE, &a_state, NULL, NULL); - - a_cpu_stats = FALSE; - lttv_option_add("cpu_stats", 'c', - "write the per cpu statistics", - "", - LTTV_OPT_NONE, &a_cpu_stats, NULL, NULL); - - a_process_stats = FALSE; - lttv_option_add("process_stats", 'p', - "write the per process statistics", - "", - LTTV_OPT_NONE, &a_process_stats, NULL, NULL); - - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/before", - LTTV_POINTER, &value)); - g_assert((before_event = *(value.v_pointer)) != NULL); - lttv_hooks_add(before_event, write_event_content, NULL); - - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/before", - LTTV_POINTER, &value)); - g_assert((before_trace = *(value.v_pointer)) != NULL); - lttv_hooks_add(before_trace, write_trace_header, NULL); - - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/before", - LTTV_POINTER, &value)); - g_assert((before_traceset = *(value.v_pointer)) != NULL); - lttv_hooks_add(before_traceset, write_traceset_header, NULL); - - g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/after", - LTTV_POINTER, &value)); - g_assert((after_traceset = *(value.v_pointer)) != NULL); - lttv_hooks_add(after_traceset, write_traceset_footer, NULL); -} - - -G_MODULE_EXPORT void destroy() -{ - g_info("Destroy textDump"); - - lttv_option_remove("output"); - - lttv_option_remove("field_names"); - - lttv_option_remove("process_state"); - - lttv_option_remove("cpu_stats"); - - lttv_option_remove("process_stats"); - - g_string_free(a_string, TRUE); - - lttv_hooks_remove_data(before_event, write_event_content, NULL); - - lttv_hooks_remove_data(before_trace, write_trace_header, NULL); - - lttv_hooks_remove_data(before_trace, write_traceset_header, NULL); - - lttv_hooks_remove_data(before_trace, write_traceset_footer, NULL); -} - - - - diff --git a/ltt/branches/poly/lttv/traceset.c b/ltt/branches/poly/lttv/traceset.c deleted file mode 100644 index ce96b99a..00000000 --- a/ltt/branches/poly/lttv/traceset.c +++ /dev/null @@ -1,171 +0,0 @@ - -#include -#include - -/* 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 _LttvTraceset { - char * filename; - GPtrArray *traces; - LttvAttribute *a; -}; - - -struct _LttvTrace { - LttTrace *t; - LttvAttribute *a; - guint ref_count; -}; - - -LttvTraceset *lttv_traceset_new() -{ - LttvTraceset *s; - - s = g_new(LttvTraceset, 1); - s->filename = NULL; - s->traces = g_ptr_array_new(); - s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - return s; -} - -char * lttv_traceset_name(LttvTraceset * s) -{ - return s->filename; -} - -LttvTrace *lttv_trace_new(LttTrace *t) -{ - LttvTrace *new_trace; - - new_trace = g_new(LttvTrace, 1); - new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - new_trace->t = t; - new_trace->ref_count = 0; - return new_trace; -} - - -LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig) -{ - int i; - LttvTraceset *s; - LttvTrace * trace; - - s = g_new(LttvTraceset, 1); - s->filename = NULL; - s->traces = g_ptr_array_new(); - for(i=0;itraces->len;i++) - { - trace = g_ptr_array_index(s_orig->traces, i); - trace->ref_count++; - - /*CHECK this used ltt_trace_copy while it may not be needed. Need to - define how traces and tracesets are shared */ - g_ptr_array_add( - s->traces, - g_ptr_array_index(s_orig->traces, i)); - } - s->a = LTTV_ATTRIBUTE(lttv_iattribute_deep_copy(LTTV_IATTRIBUTE(s_orig->a))); - return s; -} - - -LttvTraceset *lttv_traceset_load(const gchar *filename) -{ - LttvTraceset *s = g_new(LttvTraceset,1); - FILE *tf; - - s->filename = g_strdup(filename); - tf = fopen(filename,"r"); - - g_critical("NOT IMPLEMENTED : load traceset data from a XML file"); - - fclose(tf); - return s; -} - -gint lttv_traceset_save(LttvTraceset *s) -{ - FILE *tf; - - tf = fopen(s->filename, "w"); - - g_critical("NOT IMPLEMENTED : save traceset data in a XML file"); - - fclose(tf); - return 0; -} - -void lttv_traceset_destroy(LttvTraceset *s) -{ - g_ptr_array_free(s->traces, TRUE); - g_object_unref(s->a); - g_free(s); -} - -void lttv_trace_destroy(LttvTrace *t) -{ - g_object_unref(t->a); - g_free(t); -} - - -void lttv_traceset_add(LttvTraceset *s, LttvTrace *t) -{ - t->ref_count++; - g_ptr_array_add(s->traces, t); -} - - -unsigned lttv_traceset_number(LttvTraceset *s) -{ - return s->traces->len; -} - - -LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i) -{ - g_assert(s->traces->len > i); - return ((LttvTrace *)s->traces->pdata[i]); -} - - -void lttv_traceset_remove(LttvTraceset *s, unsigned i) -{ - LttvTrace * t; - g_assert(s->traces->len > i); - t = (LttvTrace *)s->traces->pdata[i]; - t->ref_count--; - g_ptr_array_remove_index(s->traces, i); -} - - -/* A set of attributes is attached to each trace set, trace and tracefile - to store user defined data as needed. */ - -LttvAttribute *lttv_traceset_attribute(LttvTraceset *s) -{ - return s->a; -} - - -LttvAttribute *lttv_trace_attribute(LttvTrace *t) -{ - return t->a; -} - - -LttTrace *lttv_trace(LttvTrace *t) -{ - return t->t; -} - -guint lttv_trace_get_ref_number(LttvTrace * t) -{ - return t->ref_count; -}