X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2FprocessTrace.c;h=700a81e1dd2488f2dcf337483b89385812b0bfc3;hb=a8c0f09de06b94e9420d286e1541c39092fff434;hp=94b5e2d90f37685abb688f70784f7e3ddcb3389b;hpb=d83f67398f1bf3c1f1372570c009071622626e4e;p=lttv.git diff --git a/ltt/branches/poly/lttv/processTrace.c b/ltt/branches/poly/lttv/processTrace.c index 94b5e2d9..700a81e1 100644 --- a/ltt/branches/poly/lttv/processTrace.c +++ b/ltt/branches/poly/lttv/processTrace.c @@ -1,6 +1,9 @@ #include #include +#include +#include +#include void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts) { @@ -33,7 +36,52 @@ lttv_context_new_trace_context(LttvTracesetContext *self) 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; itraces[i]; + trace = tc->t; + + ltt_trace_time_span_get(trace, &s, &e); + + if(i==0){ + Time_Span->startTime = s; + Time_Span->endTime = e; + }else{ + if(s.tv_sec < Time_Span->startTime.tv_sec || + (s.tv_sec == Time_Span->startTime.tv_sec + && s.tv_nsec < Time_Span->startTime.tv_nsec)) + Time_Span->startTime = s; + if(e.tv_sec > Time_Span->endTime.tv_sec || + (e.tv_sec == Time_Span->endTime.tv_sec && + e.tv_nsec > Time_Span->endTime.tv_nsec)) + Time_Span->endTime = e; + } + } } @@ -46,23 +94,28 @@ init(LttvTracesetContext *self, LttvTraceset *ts) 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->t = lttv_traceset_get(ts, 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; @@ -95,6 +148,10 @@ init(LttvTracesetContext *self, LttvTraceset *ts) 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); } @@ -108,8 +165,11 @@ void fini(LttvTracesetContext *self) 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); @@ -256,6 +316,76 @@ void lttv_traceset_context_remove_hooks(LttvTracesetContext *self, } } +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) @@ -288,7 +418,8 @@ traceset_context_instance_init (GTypeInstance *instance, gpointer g_class) static void traceset_context_finalize (LttvTracesetContext *self) { - G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACESET_CONTEXT_GET_CLASS(self)))->finalize(G_OBJECT(self)); + G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE))) + ->finalize(G_OBJECT(self)); } @@ -340,7 +471,8 @@ trace_context_instance_init (GTypeInstance *instance, gpointer g_class) static void trace_context_finalize (LttvTraceContext *self) { - G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACE_CONTEXT_GET_CLASS(self)))->finalize(G_OBJECT(self)); + G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))-> + finalize(G_OBJECT(self)); } @@ -365,7 +497,7 @@ lttv_trace_context_get_type(void) (GClassInitFunc) trace_context_class_init, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ - sizeof (LttvTracesetContext), + sizeof (LttvTraceContext), 0, /* n_preallocs */ (GInstanceInitFunc) trace_context_instance_init /* instance_init */ }; @@ -387,7 +519,8 @@ tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class) static void tracefile_context_finalize (LttvTracefileContext *self) { - G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACEFILE_CONTEXT_GET_CLASS(self)))->finalize(G_OBJECT(self)); + G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE))) + ->finalize(G_OBJECT(self)); } @@ -426,11 +559,7 @@ lttv_tracefile_context_get_type(void) 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; + return ltt_time_compare(*((LttTime *)a), *((LttTime *)b)); } @@ -440,8 +569,8 @@ gboolean get_first(gpointer key, gpointer value, gpointer user_data) { } -void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, - LttvTracesetContext *context) +void lttv_process_traceset(LttvTracesetContext *self, LttTime end, + unsigned maxNumEvents) { GPtrArray *traces = g_ptr_array_new(); @@ -461,16 +590,19 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, 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(context->before, context); - nbi = lttv_traceset_number(traceset); - // nbi = ltt_trace_set_number(traceset); + lttv_hooks_call(self->before, self); + nbi = lttv_traceset_number(self->ts); for(i = 0 ; i < nbi ; i++) { - tc = context->traces[i]; + tc = self->traces[i]; trace = tc->t; if(!lttv_hooks_call_check(tc->check, tc)) { @@ -494,13 +626,11 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, g_ptr_array_add(tracefiles, tfc); lttv_hooks_call(tfc->before, tfc); - ltt_tracefile_seek_time(tracefile, start); - event = ltt_tracefile_read(tracefile); - tfc->e = event; - - if(event != NULL) { - tfc->timestamp = ltt_event_time(event); - g_tree_insert(pqueue, &(tfc->timestamp), 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); + } } } } @@ -517,6 +647,28 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, 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. */ @@ -524,11 +676,11 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, tfc = g_tree_lookup(pqueue, &(tfc->timestamp)); g_tree_remove(pqueue, &(tfc->timestamp)); - if(!lttv_hooks_call(tfc->check_event, context)) { + 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); } @@ -536,7 +688,9 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, if(event != NULL) { tfc->e = event; tfc->timestamp = ltt_event_time(event); - g_tree_insert(pqueue, &(tfc->timestamp), tfc); + 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); } } @@ -557,7 +711,7 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, } g_assert(j == tracefiles->len); - lttv_hooks_call(context->after, context); + lttv_hooks_call(self->after, self); /* Free the traces, tracefiles and pqueue */ @@ -565,3 +719,94 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, 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); +} + +