+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
#include <lttv/processTrace.h>
#include <ltt/event.h>
LttvTraceContext *tc;
LttTrace * trace;
+ Time_Span->startTime.tv_sec = 0;
+ Time_Span->startTime.tv_nsec = 0;
+ Time_Span->endTime.tv_sec = 0;
+ Time_Span->endTime.tv_nsec = 0;
+
for(i=0; i<numTraces;i++){
tc = self->traces[i];
trace = tc->t;
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->tracefiles = g_new(LttvTracefileContext *, nb_tracefile);
for(j = 0 ; j < nb_tracefile ; j++) {
tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
+ tc->tracefiles[j] = tfc;
+ tfc->index = j;
+
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;
void fini(LttvTracesetContext *self)
{
- guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
+ guint i, j, nb_trace, nb_tracefile;
LttvTraceContext *tc;
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;
+ nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
+ ltt_trace_per_cpu_tracefile_number(tc->t);
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];
-
+ tfc = tc->tracefiles[j];
lttv_hooks_destroy(tfc->check);
lttv_hooks_destroy(tfc->before);
lttv_hooks_destroy(tfc->after);
g_object_unref(tfc->a);
g_object_unref(tfc);
}
- g_free(tc->control_tracefiles);
- g_free(tc->per_cpu_tracefiles);
+ g_free(tc->tracefiles);
g_object_unref(tc);
}
g_free(self->traces);
{
LttvTraceset *ts = self->ts;
- guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
+ guint i, j, nb_trace, nb_tracefile;
LttvTraceContext *tc;
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;
+ nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
+ ltt_trace_per_cpu_tracefile_number(tc->t);
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];
- }
+ tfc = tc->tracefiles[j];
lttv_hooks_add_list(tfc->check, check_tracefile);
lttv_hooks_add_list(tfc->before, before_tracefile);
lttv_hooks_add_list(tfc->after, after_tracefile);
{
LttvTraceset *ts = self->ts;
- guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
+ guint i, j, nb_trace, nb_tracefile;
LttvTraceContext *tc;
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;
+ nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
+ ltt_trace_per_cpu_tracefile_number(tc->t);
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];
- }
+ tfc = tc->tracefiles[j];
lttv_hooks_remove_list(tfc->check, check_tracefile);
lttv_hooks_remove_list(tfc->before, before_tracefile);
lttv_hooks_remove_list(tfc->after, after_tracefile);
gint compare_tracefile(gconstpointer a, gconstpointer b)
{
- return ltt_time_compare(*((LttTime *)a), *((LttTime *)b));
+ gint comparison;
+
+ LttvTracefileContext *trace_a = (LttvTracefileContext *)a;
+
+ LttvTracefileContext *trace_b = (LttvTracefileContext *)b;
+
+ if(trace_a == trace_b) return 0;
+ comparison = ltt_time_compare(trace_a->timestamp, trace_b->timestamp);
+ if(comparison != 0) return comparison;
+ if(trace_a->index < trace_b->index) return -1;
+ else if(trace_a->index > trace_b->index) return 1;
+ if(trace_a->t_context->index < trace_b->t_context->index) return -1;
+ else if(trace_a->t_context->index > trace_b->t_context->index) return 1;
+ g_assert(FALSE);
}
}
-void lttv_process_traceset(LttvTracesetContext *self, LttTime end,
- unsigned maxNumEvents)
+void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end)
{
- 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;
+ guint i, j, nbi, nb_tracefile;
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);
+ self->pqueue = g_tree_new(compare_tracefile);
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;
+ nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
+ ltt_trace_per_cpu_tracefile_number(tc->t);
- 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;
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfc = tc->tracefiles[j];
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);
+ (tfc->timestamp.tv_sec == end.tv_sec &&
+ tfc->timestamp.tv_nsec <= end.tv_nsec)) {
+ g_tree_insert(self->pqueue, tfc, tfc);
}
}
}
}
}
}
+}
+
+
+guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end,
+ unsigned nb_events)
+{
+ GTree *pqueue = self->pqueue;
+
+ guint id;
+
+ LttvTraceContext *tc;
+
+ LttvTracefileContext *tfc;
+
+ LttEvent *event;
+
+ unsigned count = 0;
+
+ LttTime previous_timestamp = {0, 0};
/* Get the next event from the pqueue, call its hooks,
reinsert in the pqueue the following event from the same tracefile
while(TRUE) {
tfc = NULL;
g_tree_foreach(pqueue, get_first, &tfc);
- if(tfc == NULL) break;
+ if(tfc == NULL) return count;
/* 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;
- }
- }
+ if(count >= nb_events &&
+ ltt_time_compare(tfc->timestamp, previous_timestamp) != 0)
+ return count;
+
previous_timestamp = tfc->timestamp;
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));
+ g_tree_remove(pqueue, tfc);
+ count++;
if(!lttv_hooks_call(tfc->check_event, tfc)) {
id = ltt_event_eventtype_id(tfc->e);
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_tree_insert(pqueue, tfc, tfc);
}
}
+}
+
+
+void lttv_process_traceset_end(LttvTracesetContext *self)
+{
+ guint i, j, nbi, nb_tracefile;
- /* Call all the after_tracefile, after_trace and after_traceset hooks. */
+ LttvTraceContext *tc;
- for(i = 0, j = 0 ; i < traces->len ; i++) {
- tc = traces->pdata[i];
- while(j < tracefiles->len) {
- tfc = tracefiles->pdata[j];
+ LttvTracefileContext *tfc;
- if(tfc->t_context == tc) {
- lttv_hooks_call(tfc->after, tfc);
- j++;
+ /* Call all after_traceset, after_trace, and after_tracefile hooks. */
+
+ nbi = lttv_traceset_number(self->ts);
+
+ for(i = 0 ; i < nbi ; i++) {
+ tc = self->traces[i];
+
+ /* The check hooks are called again to avoid memorizing the results
+ obtained at the beginning. CHECK if it poses a problem */
+
+ if(!lttv_hooks_call_check(tc->check, tc)) {
+ nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
+ ltt_trace_per_cpu_tracefile_number(tc->t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfc = tc->tracefiles[j];
+
+ if(!lttv_hooks_call_check(tfc->check, tfc)) {
+ lttv_hooks_call(tfc->after, tfc);
+ }
}
- else break;
+ lttv_hooks_call(tc->after, tc);
}
- lttv_hooks_call(tc->after, tc);
}
-
- g_assert(j == tracefiles->len);
lttv_hooks_call(self->after, self);
- /* Free the traces, tracefiles and pqueue */
+ /* Empty and free the pqueue */
- g_ptr_array_free(tracefiles, TRUE);
- g_ptr_array_free(traces, TRUE);
- g_tree_destroy(pqueue);
+ while(TRUE){
+ tfc = NULL;
+ g_tree_foreach(self->pqueue, get_first, &tfc);
+ if(tfc == NULL) break;
+ g_tree_remove(self->pqueue, &(tfc->timestamp));
+ }
+ g_tree_destroy(self->pqueue);
+}
+
+
+void lttv_process_traceset(LttvTracesetContext *self, LttTime end,
+ unsigned nb_events)
+{
+ lttv_process_traceset_begin(self, end);
+ lttv_process_traceset_middle(self, end, nb_events);
+ lttv_process_traceset_end(self);
}
void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
{
- guint i, nb_control, nb_per_cpu, nb_tracefile;
+ guint i, 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];
+ nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
+ ltt_trace_per_cpu_tracefile_number(self->t);
+ for(i = 0 ; i < nb_tracefile ; i++) {
+ tfc = self->tracefiles[i];
ltt_tracefile_seek_time(tfc->tf, start);
event = ltt_tracefile_read(tfc->tf);
tfc->e = event;