+++ /dev/null
-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
-
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.
+
+++ /dev/null
-
-#include <lttv/attribute.h>
-#include <ltt/ltt.h>
-
-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;
-}
-
-
+++ /dev/null
-/* This module inserts a hook in the program main loop. This hook processes
- all the events in the main tracefile. */
-
-
-#include <lttv/lttv.h>
-#include <lttv/attribute.h>
-#include <lttv/hook.h>
-#include <lttv/option.h>
-#include <lttv/module.h>
-#include <lttv/processTrace.h>
-#include <lttv/state.h>
-#include <lttv/stats.h>
-#include <ltt/trace.h>
-
-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);
-}
-
+++ /dev/null
-
- 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
-
-
+++ /dev/null
-
-#include <lttv/hook.h>
-
-
-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;
- }
-}
-
+++ /dev/null
-
-#include <lttv/iattribute.h>
-
-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;
- }
-}
-
-
+++ /dev/null
-
-#include <lttv/hook.h>
-#include <lttv/module.h>
-#include <lttv/lttv.h>
-#include <lttv/iattribute.h>
-#include <lttv/attribute.h>
-#include <lttv/option.h>
-#include <lttv/traceset.h>
-#include <ltt/trace.h>
-#include <stdio.h>
-
-
-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 */
--- /dev/null
+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
+
--- /dev/null
+
+#include <lttv/hook.h>
+#include <lttv/module.h>
+#include <lttv/lttv.h>
+#include <lttv/iattribute.h>
+#include <lttv/attribute.h>
+#include <lttv/option.h>
+#include <lttv/traceset.h>
+#include <ltt/trace.h>
+#include <stdio.h>
+
+
+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 */
--- /dev/null
+
+#include <lttv/attribute.h>
+#include <ltt/ltt.h>
+
+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;
+}
+
+
--- /dev/null
+
+ 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
+
+
--- /dev/null
+
+#include <lttv/hook.h>
+
+
+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;
+ }
+}
+
--- /dev/null
+
+#include <lttv/iattribute.h>
+
+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;
+ }
+}
+
+
--- /dev/null
+
+/* module.c : Implementation of the module loading/unloading mechanism.
+ *
+ */
+
+#include <lttv/module.h>
+
+#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");
+}
--- /dev/null
+
+#include <popt.h>
+#include <glib.h>
+#include <lttv/option.h>
+
+#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);
+
+
+}
+
--- /dev/null
+
+#include <lttv/processTrace.h>
+#include <ltt/event.h>
+#include <ltt/facility.h>
+#include <ltt/trace.h>
+#include <ltt/type.h>
+
+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; i<numTraces;i++){
+ tc = self->traces[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);
+}
+
+
--- /dev/null
+
+#include <lttv/state.h>
+#include <ltt/facility.h>
+#include <ltt/trace.h>
+#include <ltt/event.h>
+#include <ltt/type.h>
+
+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()
+{
+}
+
+
+
+
--- /dev/null
+
+#include <stdio.h>
+#include <lttv/stats.h>
+#include <ltt/facility.h>
+#include <ltt/trace.h>
+#include <ltt/event.h>
+
+#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;i<nb_attr;i++){
+ flag = 1;
+ type = lttv_attribute_get(attr, i, &name, &value);
+ switch(type) {
+ case LTTV_INT:
+ sprintf(type_value, "%d\0", *value.v_int);
+ break;
+ case LTTV_UINT:
+ sprintf(type_value, "%u\0", *value.v_uint);
+ break;
+ case LTTV_LONG:
+ sprintf(type_value, "%ld\0", *value.v_long);
+ break;
+ case LTTV_ULONG:
+ sprintf(type_value, "%lu\0", *value.v_ulong);
+ break;
+ case LTTV_FLOAT:
+ sprintf(type_value, "%f\0", (double)*value.v_float);
+ break;
+ case LTTV_DOUBLE:
+ sprintf(type_value, "%f\0", *value.v_double);
+ break;
+ case LTTV_TIME:
+ sprintf(type_value, "%10u.%09u\0", value.v_time->tv_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<VALUE type=\"%d\" name=\"%s\">",indent,type,g_quark_to_string(name));
+ fprintf(fp,"%s",type_value);
+ fprintf(fp,"</VALUE> \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, "<NODE name=\"%s\"> \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<NODE name=\"%s\"> \n",indent[0],g_quark_to_string(name)); //process NODE
+ lttv_stats_save_attribute(process_tree,indent[1], fp);
+ fprintf(fp,"%s<NODE name=\"%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<NODE name=\"%s\"> \n",indent[2],g_quark_to_string(name)); //cpu NODE
+ lttv_stats_save_attribute(cpu_tree,indent[3], fp);
+ fprintf(fp,"%s<NODE name=\"%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<NODE name=\"%s\"> \n",indent[4],g_quark_to_string(name)); //mode NODE
+ lttv_stats_save_attribute(mode_tree,indent[5], fp);
+ fprintf(fp,"%s<NODE name=\"%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<NODE name=\"%s\"> \n",indent[6],g_quark_to_string(name)); //sub_mode NODE
+ lttv_stats_save_attribute(submode_tree,indent[7], fp);
+ fprintf(fp,"%s<NODE name=\"%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</NODE> \n",indent[7]); //event_types NODE
+ fprintf(fp,"%s</NODE> \n",indent[6]); //sub_mode NODE
+ }
+ fprintf(fp,"%s</NODE> \n",indent[5]); //sub_modes NODE
+ fprintf(fp,"%s</NODE> \n",indent[4]); //mode NODE
+ }
+ fprintf(fp,"%s</NODE> \n",indent[3]); //mode_type NODE
+ fprintf(fp,"%s</NODE> \n",indent[2]); //cpu NODE
+ }
+ fprintf(fp,"%s</NODE> \n",indent[1]); //cpus NODE
+ fprintf(fp,"%s</NODE> \n", indent[0]); //process NODE
+ }
+ fprintf(fp, "</NODE>\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;len<text_len;len++){
+ if(isspace(*pos)){
+ pos++;
+ continue;
+ }
+ break;
+ }
+ if(strlen(pos) == 0)return;
+
+ len = parser->attribute->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;
+}
--- /dev/null
+
+#include <lttv/traceset.h>
+#include <stdio.h>
+
+/* 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;i<s_orig->traces->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;
+}
+++ /dev/null
-
-/* module.c : Implementation of the module loading/unloading mechanism.
- *
- */
-
-#include <lttv/module.h>
-
-#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");
-}
--- /dev/null
+/* This module inserts a hook in the program main loop. This hook processes
+ all the events in the main tracefile. */
+
+
+#include <lttv/lttv.h>
+#include <lttv/attribute.h>
+#include <lttv/hook.h>
+#include <lttv/option.h>
+#include <lttv/module.h>
+#include <lttv/processTrace.h>
+#include <lttv/state.h>
+#include <lttv/stats.h>
+#include <ltt/trace.h>
+
+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);
+}
+
--- /dev/null
+/* 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 <lttv/lttv.h>
+#include <lttv/option.h>
+#include <lttv/module.h>
+#include <lttv/hook.h>
+#include <lttv/attribute.h>
+#include <lttv/iattribute.h>
+#include <lttv/stats.h>
+#include <ltt/ltt.h>
+#include <ltt/event.h>
+#include <ltt/type.h>
+#include <ltt/trace.h>
+#include <stdio.h>
+
+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);
+}
+
+
+
+
+++ /dev/null
-
-#include <popt.h>
-#include <glib.h>
-#include <lttv/option.h>
-
-#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);
-
-
-}
-
+++ /dev/null
-
-#include <lttv/processTrace.h>
-#include <ltt/event.h>
-#include <ltt/facility.h>
-#include <ltt/trace.h>
-#include <ltt/type.h>
-
-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; i<numTraces;i++){
- tc = self->traces[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);
-}
-
-
+++ /dev/null
-
-#include <lttv/state.h>
-#include <ltt/facility.h>
-#include <ltt/trace.h>
-#include <ltt/event.h>
-#include <ltt/type.h>
-
-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()
-{
-}
-
-
-
-
+++ /dev/null
-
-#include <stdio.h>
-#include <lttv/stats.h>
-#include <ltt/facility.h>
-#include <ltt/trace.h>
-#include <ltt/event.h>
-
-#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;i<nb_attr;i++){
- flag = 1;
- type = lttv_attribute_get(attr, i, &name, &value);
- switch(type) {
- case LTTV_INT:
- sprintf(type_value, "%d\0", *value.v_int);
- break;
- case LTTV_UINT:
- sprintf(type_value, "%u\0", *value.v_uint);
- break;
- case LTTV_LONG:
- sprintf(type_value, "%ld\0", *value.v_long);
- break;
- case LTTV_ULONG:
- sprintf(type_value, "%lu\0", *value.v_ulong);
- break;
- case LTTV_FLOAT:
- sprintf(type_value, "%f\0", (double)*value.v_float);
- break;
- case LTTV_DOUBLE:
- sprintf(type_value, "%f\0", *value.v_double);
- break;
- case LTTV_TIME:
- sprintf(type_value, "%10u.%09u\0", value.v_time->tv_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<VALUE type=\"%d\" name=\"%s\">",indent,type,g_quark_to_string(name));
- fprintf(fp,"%s",type_value);
- fprintf(fp,"</VALUE> \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, "<NODE name=\"%s\"> \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<NODE name=\"%s\"> \n",indent[0],g_quark_to_string(name)); //process NODE
- lttv_stats_save_attribute(process_tree,indent[1], fp);
- fprintf(fp,"%s<NODE name=\"%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<NODE name=\"%s\"> \n",indent[2],g_quark_to_string(name)); //cpu NODE
- lttv_stats_save_attribute(cpu_tree,indent[3], fp);
- fprintf(fp,"%s<NODE name=\"%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<NODE name=\"%s\"> \n",indent[4],g_quark_to_string(name)); //mode NODE
- lttv_stats_save_attribute(mode_tree,indent[5], fp);
- fprintf(fp,"%s<NODE name=\"%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<NODE name=\"%s\"> \n",indent[6],g_quark_to_string(name)); //sub_mode NODE
- lttv_stats_save_attribute(submode_tree,indent[7], fp);
- fprintf(fp,"%s<NODE name=\"%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</NODE> \n",indent[7]); //event_types NODE
- fprintf(fp,"%s</NODE> \n",indent[6]); //sub_mode NODE
- }
- fprintf(fp,"%s</NODE> \n",indent[5]); //sub_modes NODE
- fprintf(fp,"%s</NODE> \n",indent[4]); //mode NODE
- }
- fprintf(fp,"%s</NODE> \n",indent[3]); //mode_type NODE
- fprintf(fp,"%s</NODE> \n",indent[2]); //cpu NODE
- }
- fprintf(fp,"%s</NODE> \n",indent[1]); //cpus NODE
- fprintf(fp,"%s</NODE> \n", indent[0]); //process NODE
- }
- fprintf(fp, "</NODE>\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;len<text_len;len++){
- if(isspace(*pos)){
- pos++;
- continue;
- }
- break;
- }
- if(strlen(pos) == 0)return;
-
- len = parser->attribute->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;
-}
+++ /dev/null
-/* 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 <lttv/lttv.h>
-#include <lttv/option.h>
-#include <lttv/module.h>
-#include <lttv/hook.h>
-#include <lttv/attribute.h>
-#include <lttv/iattribute.h>
-#include <lttv/stats.h>
-#include <ltt/ltt.h>
-#include <ltt/event.h>
-#include <ltt/type.h>
-#include <ltt/trace.h>
-#include <stdio.h>
-
-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);
-}
-
-
-
-
+++ /dev/null
-
-#include <lttv/traceset.h>
-#include <stdio.h>
-
-/* 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;i<s_orig->traces->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;
-}