#include <lttv/processTrace.h>
+#include <ltt/event.h>
+#include <ltt/facility.h>
-void lttv_context_init(LttvTracesetContext *self)
+void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts)
{
- LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self);
+ LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts);
}
LttvTracefileContext *
lttv_context_new_tracefile_context(LttvTracesetContext *self)
{
- LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(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;
+ }
+ }
}
nb_trace = lttv_traceset_number(ts);
self->ts = ts;
- self->traces = g_new((LttvTraceContext *), nb_trace);
+ self->traces = g_new(LttvTraceContext *, nb_trace);
self->before = lttv_hooks_new();
self->after = lttv_hooks_new();
- self->attributes = g_object_new(LTTV_ATTRIBUTE_TYPE);
+ self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
for(i = 0 ; i < nb_trace ; i++) {
- tc = self->new_trace_context();
+ tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
self->traces[i] = tc;
tc->ts_context = self;
tc->check = lttv_hooks_new();
tc->before = lttv_hooks_new();
tc->after = lttv_hooks_new();
- tc->attributes = g_object_new(LTTV_ATTRIBUTE_TYPE);
+ tc->a = 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;
- tc->control_tracefiles = g_new((LttvTracefileContext *), nb_control);
- tc->per_cpu_tracefiles = g_new((LttvTracefileContext *), 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 = self->new_tracefile_context();
+ 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(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(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_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->attributes = g_object_new(LTTV_ATTRIBUTE_TYPE);
+ tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
}
}
+ self->Time_Span = g_new(TimeInterval,1);
+ lttv_traceset_context_compute_time_span(self, self->Time_Span);
}
LttvTracefileContext *tfc;
- LttvTraceset *ts = tc->ts;
+ LttvTraceset *ts = self->ts;
+
+ g_free(self->Time_Span);
lttv_hooks_destroy(self->before);
lttv_hooks_destroy(self->after);
- g_object_unref(self->attributes);
+ //FIXME : segfault
+ // g_object_unref(self->a);
nb_trace = lttv_traceset_number(ts);
lttv_hooks_destroy(tc->check);
lttv_hooks_destroy(tc->before);
lttv_hooks_destroy(tc->after);
- g_object_unref(tc->attributes);
+ 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);
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->attributes);
+ g_object_unref(tfc->a);
g_object_unref(tfc);
}
g_free(tc->control_tracefiles);
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)
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_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++) {
tfc = tc->control_tracefiles[j];
}
else {
- tfc = tc->per_cpu_tracefiles[j];
+ tfc = tc->per_cpu_tracefiles[j-nb_control];
}
lttv_hooks_add_list(tfc->check, check_tracefile);
lttv_hooks_add_list(tfc->before, before_tracefile);
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)
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_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++) {
tfc = tc->control_tracefiles[j];
}
else {
- tfc = tc->per_cpu_tracefiles[j];
+ tfc = tc->per_cpu_tracefiles[j-nb_control];
}
lttv_hooks_remove_list(tfc->check, check_tracefile);
lttv_hooks_remove_list(tfc->before, before_tracefile);
}
-LttvTracesetContext *
+static LttvTracesetContext *
new_traceset_context(LttvTracesetContext *self)
{
- return g_object_new(LTTV_TRACESET_CONTEXT_TYPE);
+ return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
}
-LttvTraceContext *
+static LttvTraceContext *
new_trace_context(LttvTracesetContext *self)
{
- return g_object_new(LTTV_TRACE_CONTEXT_TYPE);
+ return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
}
-LttvTracefileContext *
+static LttvTracefileContext *
new_tracefile_context(LttvTracesetContext *self)
{
- return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE);
-}
-
-
-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 */
- traceset_context_class_init, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (LttvTracesetContext),
- 0, /* n_preallocs */
- traceset_context_instance_init /* instance_init */
- };
-
- type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
- &info, 0);
- }
- return type;
+ return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
}
static void
traceset_context_finalize (LttvTracesetContext *self)
{
- G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACESET_CONTEXT_TYPE))->finalize(self);
+ G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
+ ->finalize(G_OBJECT(self));
}
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- gobject_class->finalize = traceset_context_finalize;
+ gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
klass->init = init;
klass->fini = fini;
klass->new_traceset_context = new_traceset_context;
GType
-lttv_trace_context_get_type(void)
+lttv_traceset_context_get_type(void)
{
static GType type = 0;
if (type == 0) {
static const GTypeInfo info = {
- sizeof (LttvTraceContextClass),
+ sizeof (LttvTracesetContextClass),
NULL, /* base_init */
NULL, /* base_finalize */
- trace_context_class_init, /* class_init */
+ (GClassInitFunc) traceset_context_class_init, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
- sizeof (LttvTraceSetContext),
+ sizeof (LttvTracesetContext),
0, /* n_preallocs */
- trace_context_instance_init /* instance_init */
+ (GInstanceInitFunc) traceset_context_instance_init /* instance_init */
};
- type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
+ type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
&info, 0);
}
return type;
static void
trace_context_finalize (LttvTraceContext *self)
{
- G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACE_CONTEXT_TYPE))->finalize(self);
+ G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
+ finalize(G_OBJECT(self));
}
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- gobject_class->finalize = trace_context_finalize;
+ gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
}
GType
-lttv_tracefile_context_get_type(void)
+lttv_trace_context_get_type(void)
{
static GType type = 0;
if (type == 0) {
static const GTypeInfo info = {
- sizeof (LttvTracefileContextClass),
+ sizeof (LttvTraceContextClass),
NULL, /* base_init */
NULL, /* base_finalize */
- tracefile_context_class_init, /* class_init */
+ (GClassInitFunc) trace_context_class_init, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
- sizeof (LttvTracefileContext),
+ sizeof (LttvTraceContext),
0, /* n_preallocs */
- tracefile_context_instance_init /* instance_init */
+ (GInstanceInitFunc) trace_context_instance_init /* instance_init */
};
- type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType",
+ type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
&info, 0);
}
return type;
static void
tracefile_context_finalize (LttvTracefileContext *self)
{
- G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACEFILE_CONTEXT_TYPE))->finalize(self);
+ G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
+ ->finalize(G_OBJECT(self));
}
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- gobject_class->finalize = tracefile_context_finalize;
+ gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
}
-guint compare_tracefile(gconstpointer a, gconstpointer b)
+GType
+lttv_tracefile_context_get_type(void)
{
- if((LttvTime *)a->tv_sec > (LttvTime *)b->tv_sec) return 1;
- if((LttvTime *)a->tv_sec < (LttvTime *)b->tv_sec) return -1;
- if((LttvTime *)a->tv_nsec > (LttvTime *)b->tv_nsec) return 1;
- if((LttvTime *)a->tv_nsec < (LttvTime *)b->tv_nsec) return -1;
+ 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)
+{
+ if(((LttvTime *)a)->tv_sec > ((LttvTime *)b)->tv_sec) return 1;
+ if(((LttvTime *)a)->tv_sec < ((LttvTime *)b)->tv_sec) return -1;
+ if(((LttvTime *)a)->tv_nsec > ((LttvTime *)b)->tv_nsec) return 1;
+ if(((LttvTime *)a)->tv_nsec < ((LttvTime *)b)->tv_nsec) return -1;
return 0;
}
}
-void lttv_process_trace(LttvTime start, LttvTime end, LttvTraceset *traceset,
- LttvTracesetContext *context)
+void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset,
+ LttvTracesetContext *context, unsigned maxNumEvents)
{
GPtrArray *traces = g_ptr_array_new();
GTree *pqueue = g_tree_new(compare_tracefile);
- guint i, j, nbi, nbj, id;
+ guint i, j, nbi, nbj, id, nb_control, nb_cpu;
LttTrace *trace;
LttvTracefileContext *tfc;
LttEvent *event;
+ unsigned count = 0;
+ LttTime preTimestamp;
/* 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(context->before, context);
- nbi = ltt_trace_set_number(traceset);
+ nbi = lttv_traceset_number(traceset);
+ // nbi = ltt_trace_set_number(traceset);
for(i = 0 ; i < nbi ; i++) {
tc = context->traces[i];
tfc->e = event;
if(event != NULL) {
- tfc->time = ltt_event_time(event);
- g_tree_insert(pqueue, &(tfc->time), tfc);
+ tfc->timestamp = ltt_event_time(event);
+ g_tree_insert(pqueue, &(tfc->timestamp), tfc);
}
}
}
unless the tracefile is finished or the event is later than the
start time. */
- while() {
+ while(TRUE) {
tfc = NULL;
g_tree_foreach(pqueue, get_first, &tfc);
if(tfc == NULL) break;
or more tracefiles have events for the same time, hope that lookup
and remove are consistent. */
- tfc = g_tree_lookup(pqueue, &(tfc->time));
- g_tree_remove(pqueue, &(tfc->time));
+ count++;
+ if(count > maxNumEvents){
+ if(tfc->timestamp.tv_sec == preTimestamp.tv_sec &&
+ tfc->timestamp.tv_nsec == preTimestamp.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;
+ }
+ }
+ preTimestamp = tfc->timestamp;
+
+ tfc = g_tree_lookup(pqueue, &(tfc->timestamp));
+ g_tree_remove(pqueue, &(tfc->timestamp));
- if(!lttv_hooks_call(tfc->check_event, context)) {
- id = lttv_event_id(tfc->e);
+ if(!lttv_hooks_call(tfc->check_event, tfc)) {
+ id = ltt_event_eventtype_id(tfc->e);
lttv_hooks_call(tfc->before_event, tfc);
lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc);
- lttv_hooks_call(tfc->after_event, context);
+ lttv_hooks_call(tfc->after_event, tfc);
lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc);
}
event = ltt_tracefile_read(tfc->tf);
if(event != NULL) {
tfc->e = event;
- tfc->time = ltt_event_time(event);
- g_tree_insert(pqueue, &(tfc->time), tfc);
+ 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);
}
}
}
g_assert(j == tracefiles->len);
- lttv_hooks_call(after_traceset, context);
+ lttv_hooks_call(context->after, context);
/* Free the traces, tracefiles and pqueue */
g_ptr_array_free(tracefiles, TRUE);
g_ptr_array_free(traces, TRUE);
- g_tree_destroy(pqueue, TRUE);
+ g_tree_destroy(pqueue);
+}
+
+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);
}
+
+